1*cc02d7e2SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*cc02d7e2SAndroid Build Coastguard Worker 3*cc02d7e2SAndroid Build Coastguard Worker# Copyright 2015 gRPC authors. 4*cc02d7e2SAndroid Build Coastguard Worker# 5*cc02d7e2SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*cc02d7e2SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*cc02d7e2SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*cc02d7e2SAndroid Build Coastguard Worker# 9*cc02d7e2SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*cc02d7e2SAndroid Build Coastguard Worker# 11*cc02d7e2SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*cc02d7e2SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*cc02d7e2SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*cc02d7e2SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*cc02d7e2SAndroid Build Coastguard Worker# limitations under the License. 16*cc02d7e2SAndroid Build Coastguard Worker 17*cc02d7e2SAndroid Build Coastguard Workerimport argparse 18*cc02d7e2SAndroid Build Coastguard Workerimport datetime 19*cc02d7e2SAndroid Build Coastguard Workerimport os 20*cc02d7e2SAndroid Build Coastguard Workerimport re 21*cc02d7e2SAndroid Build Coastguard Workerimport subprocess 22*cc02d7e2SAndroid Build Coastguard Workerimport sys 23*cc02d7e2SAndroid Build Coastguard Worker 24*cc02d7e2SAndroid Build Coastguard Worker# find our home 25*cc02d7e2SAndroid Build Coastguard WorkerROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../..")) 26*cc02d7e2SAndroid Build Coastguard Workeros.chdir(ROOT) 27*cc02d7e2SAndroid Build Coastguard Worker 28*cc02d7e2SAndroid Build Coastguard Worker# parse command line 29*cc02d7e2SAndroid Build Coastguard Workerargp = argparse.ArgumentParser(description="copyright checker") 30*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument( 31*cc02d7e2SAndroid Build Coastguard Worker "-o", "--output", default="details", choices=["list", "details"] 32*cc02d7e2SAndroid Build Coastguard Worker) 33*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-s", "--skips", default=0, action="store_const", const=1) 34*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("-a", "--ancient", default=0, action="store_const", const=1) 35*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("--precommit", action="store_true") 36*cc02d7e2SAndroid Build Coastguard Workerargp.add_argument("--fix", action="store_true") 37*cc02d7e2SAndroid Build Coastguard Workerargs = argp.parse_args() 38*cc02d7e2SAndroid Build Coastguard Worker 39*cc02d7e2SAndroid Build Coastguard Worker# open the license text 40*cc02d7e2SAndroid Build Coastguard Workerwith open("NOTICE.txt") as f: 41*cc02d7e2SAndroid Build Coastguard Worker LICENSE_NOTICE = f.read().splitlines() 42*cc02d7e2SAndroid Build Coastguard Worker 43*cc02d7e2SAndroid Build Coastguard Worker# license format by file extension 44*cc02d7e2SAndroid Build Coastguard Worker# key is the file extension, value is a format string 45*cc02d7e2SAndroid Build Coastguard Worker# that given a line of license text, returns what should 46*cc02d7e2SAndroid Build Coastguard Worker# be in the file 47*cc02d7e2SAndroid Build Coastguard WorkerLICENSE_PREFIX_RE = { 48*cc02d7e2SAndroid Build Coastguard Worker ".bat": r"@rem\s*", 49*cc02d7e2SAndroid Build Coastguard Worker ".c": r"\s*(?://|\*)\s*", 50*cc02d7e2SAndroid Build Coastguard Worker ".cc": r"\s*(?://|\*)\s*", 51*cc02d7e2SAndroid Build Coastguard Worker ".h": r"\s*(?://|\*)\s*", 52*cc02d7e2SAndroid Build Coastguard Worker ".m": r"\s*\*\s*", 53*cc02d7e2SAndroid Build Coastguard Worker ".mm": r"\s*\*\s*", 54*cc02d7e2SAndroid Build Coastguard Worker ".php": r"\s*\*\s*", 55*cc02d7e2SAndroid Build Coastguard Worker ".js": r"\s*\*\s*", 56*cc02d7e2SAndroid Build Coastguard Worker ".py": r"#\s*", 57*cc02d7e2SAndroid Build Coastguard Worker ".pyx": r"#\s*", 58*cc02d7e2SAndroid Build Coastguard Worker ".pxd": r"#\s*", 59*cc02d7e2SAndroid Build Coastguard Worker ".pxi": r"#\s*", 60*cc02d7e2SAndroid Build Coastguard Worker ".rb": r"#\s*", 61*cc02d7e2SAndroid Build Coastguard Worker ".sh": r"#\s*", 62*cc02d7e2SAndroid Build Coastguard Worker ".proto": r"//\s*", 63*cc02d7e2SAndroid Build Coastguard Worker ".cs": r"//\s*", 64*cc02d7e2SAndroid Build Coastguard Worker ".mak": r"#\s*", 65*cc02d7e2SAndroid Build Coastguard Worker ".bazel": r"#\s*", 66*cc02d7e2SAndroid Build Coastguard Worker ".bzl": r"#\s*", 67*cc02d7e2SAndroid Build Coastguard Worker "Makefile": r"#\s*", 68*cc02d7e2SAndroid Build Coastguard Worker "Dockerfile": r"#\s*", 69*cc02d7e2SAndroid Build Coastguard Worker "BUILD": r"#\s*", 70*cc02d7e2SAndroid Build Coastguard Worker} 71*cc02d7e2SAndroid Build Coastguard Worker 72*cc02d7e2SAndroid Build Coastguard Worker# The key is the file extension, while the value is a tuple of fields 73*cc02d7e2SAndroid Build Coastguard Worker# (header, prefix, footer). 74*cc02d7e2SAndroid Build Coastguard Worker# For example, for javascript multi-line comments, the header will be '/*', the 75*cc02d7e2SAndroid Build Coastguard Worker# prefix will be '*' and the footer will be '*/'. 76*cc02d7e2SAndroid Build Coastguard Worker# If header and footer are irrelevant for a specific file extension, they are 77*cc02d7e2SAndroid Build Coastguard Worker# set to None. 78*cc02d7e2SAndroid Build Coastguard WorkerLICENSE_PREFIX_TEXT = { 79*cc02d7e2SAndroid Build Coastguard Worker ".bat": (None, "@rem", None), 80*cc02d7e2SAndroid Build Coastguard Worker ".c": (None, "//", None), 81*cc02d7e2SAndroid Build Coastguard Worker ".cc": (None, "//", None), 82*cc02d7e2SAndroid Build Coastguard Worker ".h": (None, "//", None), 83*cc02d7e2SAndroid Build Coastguard Worker ".m": ("/**", " *", " */"), 84*cc02d7e2SAndroid Build Coastguard Worker ".mm": ("/**", " *", " */"), 85*cc02d7e2SAndroid Build Coastguard Worker ".php": ("/**", " *", " */"), 86*cc02d7e2SAndroid Build Coastguard Worker ".js": ("/**", " *", " */"), 87*cc02d7e2SAndroid Build Coastguard Worker ".py": (None, "#", None), 88*cc02d7e2SAndroid Build Coastguard Worker ".pyx": (None, "#", None), 89*cc02d7e2SAndroid Build Coastguard Worker ".pxd": (None, "#", None), 90*cc02d7e2SAndroid Build Coastguard Worker ".pxi": (None, "#", None), 91*cc02d7e2SAndroid Build Coastguard Worker ".rb": (None, "#", None), 92*cc02d7e2SAndroid Build Coastguard Worker ".sh": (None, "#", None), 93*cc02d7e2SAndroid Build Coastguard Worker ".proto": (None, "//", None), 94*cc02d7e2SAndroid Build Coastguard Worker ".cs": (None, "//", None), 95*cc02d7e2SAndroid Build Coastguard Worker ".mak": (None, "#", None), 96*cc02d7e2SAndroid Build Coastguard Worker ".bazel": (None, "#", None), 97*cc02d7e2SAndroid Build Coastguard Worker ".bzl": (None, "#", None), 98*cc02d7e2SAndroid Build Coastguard Worker "Makefile": (None, "#", None), 99*cc02d7e2SAndroid Build Coastguard Worker "Dockerfile": (None, "#", None), 100*cc02d7e2SAndroid Build Coastguard Worker "BUILD": (None, "#", None), 101*cc02d7e2SAndroid Build Coastguard Worker} 102*cc02d7e2SAndroid Build Coastguard Worker 103*cc02d7e2SAndroid Build Coastguard Worker_EXEMPT = frozenset( 104*cc02d7e2SAndroid Build Coastguard Worker ( 105*cc02d7e2SAndroid Build Coastguard Worker # Generated protocol compiler output. 106*cc02d7e2SAndroid Build Coastguard Worker "examples/python/helloworld/helloworld_pb2.py", 107*cc02d7e2SAndroid Build Coastguard Worker "examples/python/helloworld/helloworld_pb2_grpc.py", 108*cc02d7e2SAndroid Build Coastguard Worker "examples/python/multiplex/helloworld_pb2.py", 109*cc02d7e2SAndroid Build Coastguard Worker "examples/python/multiplex/helloworld_pb2_grpc.py", 110*cc02d7e2SAndroid Build Coastguard Worker "examples/python/multiplex/route_guide_pb2.py", 111*cc02d7e2SAndroid Build Coastguard Worker "examples/python/multiplex/route_guide_pb2_grpc.py", 112*cc02d7e2SAndroid Build Coastguard Worker "examples/python/route_guide/route_guide_pb2.py", 113*cc02d7e2SAndroid Build Coastguard Worker "examples/python/route_guide/route_guide_pb2_grpc.py", 114*cc02d7e2SAndroid Build Coastguard Worker # Generated doxygen config file 115*cc02d7e2SAndroid Build Coastguard Worker "tools/doxygen/Doxyfile.php", 116*cc02d7e2SAndroid Build Coastguard Worker # An older file originally from outside gRPC. 117*cc02d7e2SAndroid Build Coastguard Worker "src/php/tests/bootstrap.php", 118*cc02d7e2SAndroid Build Coastguard Worker # census.proto copied from github 119*cc02d7e2SAndroid Build Coastguard Worker "tools/grpcz/census.proto", 120*cc02d7e2SAndroid Build Coastguard Worker # status.proto copied from googleapis 121*cc02d7e2SAndroid Build Coastguard Worker "src/proto/grpc/status/status.proto", 122*cc02d7e2SAndroid Build Coastguard Worker # Gradle wrappers used to build for Android 123*cc02d7e2SAndroid Build Coastguard Worker "examples/android/helloworld/gradlew.bat", 124*cc02d7e2SAndroid Build Coastguard Worker "src/android/test/interop/gradlew.bat", 125*cc02d7e2SAndroid Build Coastguard Worker # Designer-generated source 126*cc02d7e2SAndroid Build Coastguard Worker "examples/csharp/HelloworldXamarin/Droid/Resources/Resource.designer.cs", 127*cc02d7e2SAndroid Build Coastguard Worker "examples/csharp/HelloworldXamarin/iOS/ViewController.designer.cs", 128*cc02d7e2SAndroid Build Coastguard Worker # BoringSSL generated header. It has commit version information at the head 129*cc02d7e2SAndroid Build Coastguard Worker # of the file so we cannot check the license info. 130*cc02d7e2SAndroid Build Coastguard Worker "src/boringssl/boringssl_prefix_symbols.h", 131*cc02d7e2SAndroid Build Coastguard Worker ) 132*cc02d7e2SAndroid Build Coastguard Worker) 133*cc02d7e2SAndroid Build Coastguard Worker 134*cc02d7e2SAndroid Build Coastguard Worker_ENFORCE_CPP_STYLE_COMMENT_PATH_PREFIX = tuple( 135*cc02d7e2SAndroid Build Coastguard Worker [ 136*cc02d7e2SAndroid Build Coastguard Worker "include/grpc++/", 137*cc02d7e2SAndroid Build Coastguard Worker "include/grpcpp/", 138*cc02d7e2SAndroid Build Coastguard Worker "src/core/", 139*cc02d7e2SAndroid Build Coastguard Worker "src/cpp/", 140*cc02d7e2SAndroid Build Coastguard Worker "test/core/", 141*cc02d7e2SAndroid Build Coastguard Worker "test/cpp/", 142*cc02d7e2SAndroid Build Coastguard Worker "fuzztest/", 143*cc02d7e2SAndroid Build Coastguard Worker ] 144*cc02d7e2SAndroid Build Coastguard Worker) 145*cc02d7e2SAndroid Build Coastguard Worker 146*cc02d7e2SAndroid Build Coastguard WorkerRE_YEAR = ( 147*cc02d7e2SAndroid Build Coastguard Worker r"Copyright (?P<first_year>[0-9]+\-)?(?P<last_year>[0-9]+) ([Tt]he )?gRPC" 148*cc02d7e2SAndroid Build Coastguard Worker r" [Aa]uthors(\.|)" 149*cc02d7e2SAndroid Build Coastguard Worker) 150*cc02d7e2SAndroid Build Coastguard WorkerRE_LICENSE = dict( 151*cc02d7e2SAndroid Build Coastguard Worker ( 152*cc02d7e2SAndroid Build Coastguard Worker k, 153*cc02d7e2SAndroid Build Coastguard Worker r"\n".join( 154*cc02d7e2SAndroid Build Coastguard Worker LICENSE_PREFIX_RE[k] 155*cc02d7e2SAndroid Build Coastguard Worker + (RE_YEAR if re.search(RE_YEAR, line) else re.escape(line)) 156*cc02d7e2SAndroid Build Coastguard Worker for line in LICENSE_NOTICE 157*cc02d7e2SAndroid Build Coastguard Worker ), 158*cc02d7e2SAndroid Build Coastguard Worker ) 159*cc02d7e2SAndroid Build Coastguard Worker for k, v in list(LICENSE_PREFIX_RE.items()) 160*cc02d7e2SAndroid Build Coastguard Worker) 161*cc02d7e2SAndroid Build Coastguard Worker 162*cc02d7e2SAndroid Build Coastguard WorkerRE_C_STYLE_COMMENT_START = r"^/\*\s*\n" 163*cc02d7e2SAndroid Build Coastguard WorkerRE_C_STYLE_COMMENT_OPTIONAL_LINE = r"(?:\s*\*\s*\n)*" 164*cc02d7e2SAndroid Build Coastguard WorkerRE_C_STYLE_COMMENT_END = r"\s*\*/" 165*cc02d7e2SAndroid Build Coastguard WorkerRE_C_STYLE_COMMENT_LICENSE = ( 166*cc02d7e2SAndroid Build Coastguard Worker RE_C_STYLE_COMMENT_START 167*cc02d7e2SAndroid Build Coastguard Worker + RE_C_STYLE_COMMENT_OPTIONAL_LINE 168*cc02d7e2SAndroid Build Coastguard Worker + r"\n".join( 169*cc02d7e2SAndroid Build Coastguard Worker r"\s*(?:\*)\s*" 170*cc02d7e2SAndroid Build Coastguard Worker + (RE_YEAR if re.search(RE_YEAR, line) else re.escape(line)) 171*cc02d7e2SAndroid Build Coastguard Worker for line in LICENSE_NOTICE 172*cc02d7e2SAndroid Build Coastguard Worker ) 173*cc02d7e2SAndroid Build Coastguard Worker + r"\n" 174*cc02d7e2SAndroid Build Coastguard Worker + RE_C_STYLE_COMMENT_OPTIONAL_LINE 175*cc02d7e2SAndroid Build Coastguard Worker + RE_C_STYLE_COMMENT_END 176*cc02d7e2SAndroid Build Coastguard Worker) 177*cc02d7e2SAndroid Build Coastguard WorkerRE_CPP_STYLE_COMMENT_LICENSE = r"\n".join( 178*cc02d7e2SAndroid Build Coastguard Worker r"\s*(?://)\s*" + (RE_YEAR if re.search(RE_YEAR, line) else re.escape(line)) 179*cc02d7e2SAndroid Build Coastguard Worker for line in LICENSE_NOTICE 180*cc02d7e2SAndroid Build Coastguard Worker) 181*cc02d7e2SAndroid Build Coastguard Worker 182*cc02d7e2SAndroid Build Coastguard WorkerYEAR = datetime.datetime.now().year 183*cc02d7e2SAndroid Build Coastguard Worker 184*cc02d7e2SAndroid Build Coastguard WorkerLICENSE_YEAR = f"Copyright {YEAR} gRPC authors." 185*cc02d7e2SAndroid Build Coastguard Worker 186*cc02d7e2SAndroid Build Coastguard Worker 187*cc02d7e2SAndroid Build Coastguard Workerdef join_license_text(header, prefix, footer, notice): 188*cc02d7e2SAndroid Build Coastguard Worker text = (header + "\n") if header else "" 189*cc02d7e2SAndroid Build Coastguard Worker 190*cc02d7e2SAndroid Build Coastguard Worker def add_prefix(prefix, line): 191*cc02d7e2SAndroid Build Coastguard Worker # Don't put whitespace between prefix and empty line to avoid having 192*cc02d7e2SAndroid Build Coastguard Worker # trailing whitespaces. 193*cc02d7e2SAndroid Build Coastguard Worker return prefix + ("" if len(line) == 0 else " ") + line 194*cc02d7e2SAndroid Build Coastguard Worker 195*cc02d7e2SAndroid Build Coastguard Worker text += "\n".join( 196*cc02d7e2SAndroid Build Coastguard Worker add_prefix(prefix, (LICENSE_YEAR if re.search(RE_YEAR, line) else line)) 197*cc02d7e2SAndroid Build Coastguard Worker for line in LICENSE_NOTICE 198*cc02d7e2SAndroid Build Coastguard Worker ) 199*cc02d7e2SAndroid Build Coastguard Worker text += "\n" 200*cc02d7e2SAndroid Build Coastguard Worker if footer: 201*cc02d7e2SAndroid Build Coastguard Worker text += footer + "\n" 202*cc02d7e2SAndroid Build Coastguard Worker return text 203*cc02d7e2SAndroid Build Coastguard Worker 204*cc02d7e2SAndroid Build Coastguard Worker 205*cc02d7e2SAndroid Build Coastguard WorkerLICENSE_TEXT = dict( 206*cc02d7e2SAndroid Build Coastguard Worker ( 207*cc02d7e2SAndroid Build Coastguard Worker k, 208*cc02d7e2SAndroid Build Coastguard Worker join_license_text( 209*cc02d7e2SAndroid Build Coastguard Worker LICENSE_PREFIX_TEXT[k][0], 210*cc02d7e2SAndroid Build Coastguard Worker LICENSE_PREFIX_TEXT[k][1], 211*cc02d7e2SAndroid Build Coastguard Worker LICENSE_PREFIX_TEXT[k][2], 212*cc02d7e2SAndroid Build Coastguard Worker LICENSE_NOTICE, 213*cc02d7e2SAndroid Build Coastguard Worker ), 214*cc02d7e2SAndroid Build Coastguard Worker ) 215*cc02d7e2SAndroid Build Coastguard Worker for k, v in list(LICENSE_PREFIX_TEXT.items()) 216*cc02d7e2SAndroid Build Coastguard Worker) 217*cc02d7e2SAndroid Build Coastguard Worker 218*cc02d7e2SAndroid Build Coastguard Workerif args.precommit: 219*cc02d7e2SAndroid Build Coastguard Worker FILE_LIST_COMMAND = ( 220*cc02d7e2SAndroid Build Coastguard Worker "git status -z | grep -Poz '(?<=^[MARC][MARCD ] )[^\s]+'" 221*cc02d7e2SAndroid Build Coastguard Worker ) 222*cc02d7e2SAndroid Build Coastguard Workerelse: 223*cc02d7e2SAndroid Build Coastguard Worker FILE_LIST_COMMAND = ( 224*cc02d7e2SAndroid Build Coastguard Worker "git ls-tree -r --name-only -r HEAD | " 225*cc02d7e2SAndroid Build Coastguard Worker "grep -v ^third_party/ |" 226*cc02d7e2SAndroid Build Coastguard Worker 'grep -v "\(ares_config.h\|ares_build.h\)"' 227*cc02d7e2SAndroid Build Coastguard Worker ) 228*cc02d7e2SAndroid Build Coastguard Worker 229*cc02d7e2SAndroid Build Coastguard Worker 230*cc02d7e2SAndroid Build Coastguard Workerdef load(name): 231*cc02d7e2SAndroid Build Coastguard Worker with open(name) as f: 232*cc02d7e2SAndroid Build Coastguard Worker return f.read() 233*cc02d7e2SAndroid Build Coastguard Worker 234*cc02d7e2SAndroid Build Coastguard Worker 235*cc02d7e2SAndroid Build Coastguard Workerdef save(name, text): 236*cc02d7e2SAndroid Build Coastguard Worker with open(name, "w") as f: 237*cc02d7e2SAndroid Build Coastguard Worker f.write(text) 238*cc02d7e2SAndroid Build Coastguard Worker 239*cc02d7e2SAndroid Build Coastguard Worker 240*cc02d7e2SAndroid Build Coastguard Workerassert re.search(RE_LICENSE["Makefile"], load("Makefile")) 241*cc02d7e2SAndroid Build Coastguard Worker 242*cc02d7e2SAndroid Build Coastguard Worker 243*cc02d7e2SAndroid Build Coastguard Workerdef log(cond, why, filename): 244*cc02d7e2SAndroid Build Coastguard Worker if not cond: 245*cc02d7e2SAndroid Build Coastguard Worker return 246*cc02d7e2SAndroid Build Coastguard Worker if args.output == "details": 247*cc02d7e2SAndroid Build Coastguard Worker print(("%s: %s" % (why, filename))) 248*cc02d7e2SAndroid Build Coastguard Worker else: 249*cc02d7e2SAndroid Build Coastguard Worker print(filename) 250*cc02d7e2SAndroid Build Coastguard Worker 251*cc02d7e2SAndroid Build Coastguard Worker 252*cc02d7e2SAndroid Build Coastguard Workerdef write_copyright(license_text, file_text, filename): 253*cc02d7e2SAndroid Build Coastguard Worker shebang = "" 254*cc02d7e2SAndroid Build Coastguard Worker lines = file_text.split("\n") 255*cc02d7e2SAndroid Build Coastguard Worker if lines and lines[0].startswith("#!"): 256*cc02d7e2SAndroid Build Coastguard Worker shebang = lines[0] + "\n" 257*cc02d7e2SAndroid Build Coastguard Worker file_text = file_text[len(shebang) :] 258*cc02d7e2SAndroid Build Coastguard Worker 259*cc02d7e2SAndroid Build Coastguard Worker rewritten_text = shebang + license_text + "\n" + file_text 260*cc02d7e2SAndroid Build Coastguard Worker with open(filename, "w") as f: 261*cc02d7e2SAndroid Build Coastguard Worker f.write(rewritten_text) 262*cc02d7e2SAndroid Build Coastguard Worker 263*cc02d7e2SAndroid Build Coastguard Worker 264*cc02d7e2SAndroid Build Coastguard Workerdef replace_copyright(license_text, file_text, filename): 265*cc02d7e2SAndroid Build Coastguard Worker m = re.search(RE_C_STYLE_COMMENT_LICENSE, text) 266*cc02d7e2SAndroid Build Coastguard Worker if m: 267*cc02d7e2SAndroid Build Coastguard Worker rewritten_text = license_text + file_text[m.end() :] 268*cc02d7e2SAndroid Build Coastguard Worker with open(filename, "w") as f: 269*cc02d7e2SAndroid Build Coastguard Worker f.write(rewritten_text) 270*cc02d7e2SAndroid Build Coastguard Worker return True 271*cc02d7e2SAndroid Build Coastguard Worker return False 272*cc02d7e2SAndroid Build Coastguard Worker 273*cc02d7e2SAndroid Build Coastguard Worker 274*cc02d7e2SAndroid Build Coastguard Worker# scan files, validate the text 275*cc02d7e2SAndroid Build Coastguard Workerok = True 276*cc02d7e2SAndroid Build Coastguard Workerfilename_list = [] 277*cc02d7e2SAndroid Build Coastguard Workertry: 278*cc02d7e2SAndroid Build Coastguard Worker filename_list = ( 279*cc02d7e2SAndroid Build Coastguard Worker subprocess.check_output(FILE_LIST_COMMAND, shell=True) 280*cc02d7e2SAndroid Build Coastguard Worker .decode() 281*cc02d7e2SAndroid Build Coastguard Worker .splitlines() 282*cc02d7e2SAndroid Build Coastguard Worker ) 283*cc02d7e2SAndroid Build Coastguard Workerexcept subprocess.CalledProcessError: 284*cc02d7e2SAndroid Build Coastguard Worker sys.exit(0) 285*cc02d7e2SAndroid Build Coastguard Worker 286*cc02d7e2SAndroid Build Coastguard Workerfor filename in filename_list: 287*cc02d7e2SAndroid Build Coastguard Worker enforce_cpp_style_comment = False 288*cc02d7e2SAndroid Build Coastguard Worker if filename in _EXEMPT: 289*cc02d7e2SAndroid Build Coastguard Worker continue 290*cc02d7e2SAndroid Build Coastguard Worker # Skip check for upb generated code. 291*cc02d7e2SAndroid Build Coastguard Worker if ( 292*cc02d7e2SAndroid Build Coastguard Worker filename.endswith(".upb.h") 293*cc02d7e2SAndroid Build Coastguard Worker or filename.endswith(".upbdefs.h") 294*cc02d7e2SAndroid Build Coastguard Worker or filename.endswith(".upbdefs.c") 295*cc02d7e2SAndroid Build Coastguard Worker or filename.endswith(".upb_minitable.h") 296*cc02d7e2SAndroid Build Coastguard Worker or filename.endswith(".upb_minitable.c") 297*cc02d7e2SAndroid Build Coastguard Worker ): 298*cc02d7e2SAndroid Build Coastguard Worker continue 299*cc02d7e2SAndroid Build Coastguard Worker # Allow empty __init__.py files for code generated by xds_protos 300*cc02d7e2SAndroid Build Coastguard Worker if filename.startswith("tools/distrib/python/xds_protos") and ( 301*cc02d7e2SAndroid Build Coastguard Worker filename.endswith("__init__.py") 302*cc02d7e2SAndroid Build Coastguard Worker or filename.endswith("generated_file_import_test.py") 303*cc02d7e2SAndroid Build Coastguard Worker ): 304*cc02d7e2SAndroid Build Coastguard Worker continue 305*cc02d7e2SAndroid Build Coastguard Worker ext = os.path.splitext(filename)[1] 306*cc02d7e2SAndroid Build Coastguard Worker base = os.path.basename(filename) 307*cc02d7e2SAndroid Build Coastguard Worker if filename.startswith(_ENFORCE_CPP_STYLE_COMMENT_PATH_PREFIX) and ext in [ 308*cc02d7e2SAndroid Build Coastguard Worker ".cc", 309*cc02d7e2SAndroid Build Coastguard Worker ".h", 310*cc02d7e2SAndroid Build Coastguard Worker ]: 311*cc02d7e2SAndroid Build Coastguard Worker enforce_cpp_style_comment = True 312*cc02d7e2SAndroid Build Coastguard Worker re_license = RE_CPP_STYLE_COMMENT_LICENSE 313*cc02d7e2SAndroid Build Coastguard Worker license_text = LICENSE_TEXT[ext] 314*cc02d7e2SAndroid Build Coastguard Worker elif ext in RE_LICENSE: 315*cc02d7e2SAndroid Build Coastguard Worker re_license = RE_LICENSE[ext] 316*cc02d7e2SAndroid Build Coastguard Worker license_text = LICENSE_TEXT[ext] 317*cc02d7e2SAndroid Build Coastguard Worker elif base in RE_LICENSE: 318*cc02d7e2SAndroid Build Coastguard Worker re_license = RE_LICENSE[base] 319*cc02d7e2SAndroid Build Coastguard Worker license_text = LICENSE_TEXT[base] 320*cc02d7e2SAndroid Build Coastguard Worker else: 321*cc02d7e2SAndroid Build Coastguard Worker log(args.skips, "skip", filename) 322*cc02d7e2SAndroid Build Coastguard Worker continue 323*cc02d7e2SAndroid Build Coastguard Worker try: 324*cc02d7e2SAndroid Build Coastguard Worker text = load(filename) 325*cc02d7e2SAndroid Build Coastguard Worker except: 326*cc02d7e2SAndroid Build Coastguard Worker continue 327*cc02d7e2SAndroid Build Coastguard Worker m = re.search(re_license, text) 328*cc02d7e2SAndroid Build Coastguard Worker if m: 329*cc02d7e2SAndroid Build Coastguard Worker pass 330*cc02d7e2SAndroid Build Coastguard Worker elif enforce_cpp_style_comment: 331*cc02d7e2SAndroid Build Coastguard Worker log( 332*cc02d7e2SAndroid Build Coastguard Worker 1, 333*cc02d7e2SAndroid Build Coastguard Worker "copyright missing or does not use cpp-style copyright header", 334*cc02d7e2SAndroid Build Coastguard Worker filename, 335*cc02d7e2SAndroid Build Coastguard Worker ) 336*cc02d7e2SAndroid Build Coastguard Worker if args.fix: 337*cc02d7e2SAndroid Build Coastguard Worker # Attempt fix: search for c-style copyright header and replace it 338*cc02d7e2SAndroid Build Coastguard Worker # with cpp-style copyright header. If that doesn't work 339*cc02d7e2SAndroid Build Coastguard Worker # (e.g. missing copyright header), write cpp-style copyright header. 340*cc02d7e2SAndroid Build Coastguard Worker if not replace_copyright(license_text, text, filename): 341*cc02d7e2SAndroid Build Coastguard Worker write_copyright(license_text, text, filename) 342*cc02d7e2SAndroid Build Coastguard Worker ok = False 343*cc02d7e2SAndroid Build Coastguard Worker elif "DO NOT EDIT" not in text: 344*cc02d7e2SAndroid Build Coastguard Worker if args.fix: 345*cc02d7e2SAndroid Build Coastguard Worker write_copyright(license_text, text, filename) 346*cc02d7e2SAndroid Build Coastguard Worker log(1, "copyright missing (fixed)", filename) 347*cc02d7e2SAndroid Build Coastguard Worker else: 348*cc02d7e2SAndroid Build Coastguard Worker log(1, "copyright missing", filename) 349*cc02d7e2SAndroid Build Coastguard Worker ok = False 350*cc02d7e2SAndroid Build Coastguard Worker 351*cc02d7e2SAndroid Build Coastguard Workerif not ok and not args.fix: 352*cc02d7e2SAndroid Build Coastguard Worker print( 353*cc02d7e2SAndroid Build Coastguard Worker "You may use following command to automatically fix copyright headers:" 354*cc02d7e2SAndroid Build Coastguard Worker ) 355*cc02d7e2SAndroid Build Coastguard Worker print(" tools/distrib/check_copyright.py --fix") 356*cc02d7e2SAndroid Build Coastguard Worker 357*cc02d7e2SAndroid Build Coastguard Workersys.exit(0 if ok else 1) 358