def Sync(api_root, mode, labels, shadow): pkg_deps = [] with tempfile.TemporaryDirectory() as tmp: dst_dir = pathlib.Path(tmp).joinpath("b") for label in labels: pkg_deps += SyncProtoFile(mode, utils.BazelBinPathForOutputArtifact(label, '.v2.proto'), dst_dir) pkg_deps += SyncProtoFile( mode, utils.BazelBinPathForOutputArtifact( label, '.v3.envoy_internal.proto' if shadow else '.v3.proto'), dst_dir) SyncBuildFiles(mode, dst_dir) current_api_dir = pathlib.Path(tmp).joinpath("a") current_api_dir.mkdir(0o755, True, True) api_root_path = pathlib.Path(api_root) GenerateCurrentApiDir(api_root_path, current_api_dir) # These support files are handled manually. for f in [ 'envoy/annotations/resource.proto', 'envoy/annotations/deprecation.proto', 'envoy/annotations/BUILD' ]: copy_dst_dir = pathlib.Path(dst_dir, os.path.dirname(f)) copy_dst_dir.mkdir(exist_ok=True) shutil.copy(str(pathlib.Path(api_root, f)), str(copy_dst_dir)) diff = subprocess.run(['diff', '-Npur', "a", "b"], cwd=tmp, stdout=subprocess.PIPE).stdout if diff.strip(): if mode == "check": print("Please apply following patch to directory '{}'".format(api_root), file=sys.stderr) print(diff.decode(), file=sys.stderr) sys.exit(1) if mode == "fix": src_files = set(str(p.relative_to(current_api_dir)) for p in current_api_dir.rglob('*')) dst_files = set(str(p.relative_to(dst_dir)) for p in dst_dir.rglob('*')) deleted_files = src_files.difference(dst_files) if deleted_files: print('The following files will be deleted: %s' % sorted(deleted_files)) print( 'If this is not intended, please see https://github.com/envoyproxy/envoy/blob/master/api/STYLE.md#adding-an-extension-configuration-to-the-api.' ) if input('Delete files? [yN] ').strip().lower() == 'y': subprocess.run(['patch', '-p1'], input=diff, cwd=str(api_root_path.resolve())) else: sys.exit(1) else: subprocess.run(['patch', '-p1'], input=diff, cwd=str(api_root_path.resolve())) with open(os.path.join(api_root, 'BUILD'), 'w') as f: formatted_deps = '\n'.join( ' "%s",' % d for d in sorted(set(pkg_deps), key=BuildOrderKey)) f.write(TOP_LEVEL_API_BUILD_FILE_TEMPLATE.substitute(deps=formatted_deps))
def Sync(api_root, mode, labels, shadow): pkg_deps = [] with tempfile.TemporaryDirectory() as tmp: dst_dir = pathlib.Path(tmp).joinpath("b") for label in labels: pkg_deps += SyncProtoFile( mode, utils.BazelBinPathForOutputArtifact(label, '.v2.proto'), dst_dir) pkg_deps += SyncProtoFile( mode, utils.BazelBinPathForOutputArtifact( label, '.v3alpha.envoy_internal.proto' if shadow else '.v3alpha.proto'), dst_dir) SyncBuildFiles(mode, dst_dir) current_api_dir = pathlib.Path(tmp).joinpath("a") current_api_dir.mkdir(0o755, True, True) api_root_path = pathlib.Path(api_root) GenerateCurrentApiDir(api_root_path, current_api_dir) # These support files are handled manually. for f in [ 'envoy/annotations/resource.proto', 'envoy/annotations/deprecation.proto', 'envoy/annotations/BUILD' ]: copy_dst_dir = pathlib.Path(dst_dir, os.path.dirname(f)) copy_dst_dir.mkdir(exist_ok=True) shutil.copy(str(pathlib.Path(api_root, f)), str(copy_dst_dir)) diff = subprocess.run(['diff', '-Npur', "a", "b"], cwd=tmp, stdout=subprocess.PIPE).stdout if diff.strip(): if mode == "check": print("Please apply following patch to directory '{}'".format( api_root), file=sys.stderr) print(diff.decode(), file=sys.stderr) sys.exit(1) if mode == "fix": subprocess.run(['patch', '-p1'], input=diff, cwd=str(api_root_path.resolve())) with open(os.path.join(api_root, 'BUILD'), 'w') as f: formatted_deps = '\n'.join( ' "%s",' % d for d in sorted(set(pkg_deps), key=BuildOrderKey)) f.write( TOP_LEVEL_API_BUILD_FILE_TEMPLATE.substitute(deps=formatted_deps))
def LabelPaths(label, src_suffix): """Compute single proto file source/destination paths from a Bazel proto label. Args: label: Bazel source proto label string. src_suffix: suffix string to append to source path. Returns: source, destination path tuple. The source indicates where in the Bazel cache the protoxform.py artifact with src_suffix can be found. The destination is a provisional path in the Envoy source tree for copying the contents of source when run in fix mode. """ src = utils.BazelBinPathForOutputArtifact(label, src_suffix) dst = 'api/%s' % utils.ProtoFileCanonicalFromLabel(label) return src, dst
def Sync(api_root, mode, labels, shadow): with tempfile.TemporaryDirectory() as tmp: dst_dir = pathlib.Path(tmp).joinpath("b") paths = [] for label in labels: paths.append(utils.BazelBinPathForOutputArtifact(label, '.active_or_frozen.proto')) paths.append( utils.BazelBinPathForOutputArtifact( label, '.next_major_version_candidate.envoy_internal.proto' if shadow else '.next_major_version_candidate.proto')) dst_src_paths = defaultdict(list) for path in paths: if os.stat(path).st_size > 0: dst_src_paths[GetAbsDestinationPath(dst_dir, path)].append(path) with mp.Pool() as p: pkg_deps = p.map(SyncProtoFile, dst_src_paths.items()) SyncBuildFiles(mode, dst_dir) current_api_dir = pathlib.Path(tmp).joinpath("a") current_api_dir.mkdir(0o755, True, True) api_root_path = pathlib.Path(api_root) GenerateCurrentApiDir(api_root_path, current_api_dir) # These support files are handled manually. for f in [ 'envoy/annotations/resource.proto', 'envoy/annotations/deprecation.proto', 'envoy/annotations/BUILD' ]: copy_dst_dir = pathlib.Path(dst_dir, os.path.dirname(f)) copy_dst_dir.mkdir(exist_ok=True) shutil.copy(str(pathlib.Path(api_root, f)), str(copy_dst_dir)) diff = subprocess.run(['diff', '-Npur', "a", "b"], cwd=tmp, stdout=subprocess.PIPE).stdout if diff.strip(): if mode == "check": print("Please apply following patch to directory '{}'".format(api_root), file=sys.stderr) print(diff.decode(), file=sys.stderr) sys.exit(1) if mode == "fix": git_status = GitStatus(api_root) if git_status: print('git status indicates a dirty API tree:\n%s' % git_status) print( 'Proto formatting may overwrite or delete files in the above list with no git backup.' ) if input('Continue? [yN] ').strip().lower() != 'y': sys.exit(1) src_files = set(str(p.relative_to(current_api_dir)) for p in current_api_dir.rglob('*')) dst_files = set(str(p.relative_to(dst_dir)) for p in dst_dir.rglob('*')) deleted_files = src_files.difference(dst_files) if deleted_files: print('The following files will be deleted: %s' % sorted(deleted_files)) print( 'If this is not intended, please see https://github.com/envoyproxy/envoy/blob/master/api/STYLE.md#adding-an-extension-configuration-to-the-api.' ) if input('Delete files? [yN] ').strip().lower() == 'y': subprocess.run(['patch', '-p1'], input=diff, cwd=str(api_root_path.resolve())) else: sys.exit(1) else: subprocess.run(['patch', '-p1'], input=diff, cwd=str(api_root_path.resolve()))
if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--mode', choices=['check', 'fix']) parser.add_argument('--api_repo', default='envoy_api') parser.add_argument('--api_root', default='api') parser.add_argument('labels', nargs='*') args = parser.parse_args() with tempfile.TemporaryDirectory() as tmp: dst_dir = pathlib.Path(tmp).joinpath("b") for label in args.labels: SyncProtoFile( args.mode, utils.BazelBinPathForOutputArtifact(label, '.v2.proto'), dst_dir) SyncProtoFile( args.mode, utils.BazelBinPathForOutputArtifact(label, '.v3alpha.proto'), dst_dir) SyncBuildFiles(args.mode, dst_dir) current_api_dir = pathlib.Path(tmp).joinpath("a") current_api_dir.mkdir(0o755, True, True) api_root = pathlib.Path(args.api_root) GenerateCurrentApiDir(api_root, current_api_dir) diff = subprocess.run(['diff', '-Npur', "a", "b"], cwd=tmp, stdout=subprocess.PIPE).stdout