1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- import sys
- import os
- import subprocess
- import re
- import argparse
- import shutil
- FROM_RE = re.compile(r"((?:struct|class)\s+\S+\s+)final\s*:")
- TO_RE = r"\1:"
- def parse_args() -> argparse.Namespace:
- parser = argparse.ArgumentParser()
- parser.add_argument('--outputs', nargs='+', required=True)
- parser.add_argument('subcommand', nargs='+')
- return parser.parse_args()
- def patch_proto_file(text: str) -> tuple[str, int]:
- num_patches = 0
- patches = [
- (re.compile(r"((?:struct|class)\s+\S+\s+)final\s*:"), r"\1:"),
- (re.compile(r'(#include.*?)(\.proto\.h)"'), r'\1.pb.h"')
- ]
- for from_re, to_re in patches:
- text, n = re.subn(from_re, to_re, text)
- num_patches += n
- return text, num_patches
- def strip_file_ext(path: str) -> str:
- dirname, filename = os.path.dirname(path), os.path.basename(path)
- filename = filename.split('.')[0]
- return os.path.join(dirname, filename)
- def change_file_ext(path: str, change_map: dict[str, str]) -> str:
- dirname, filename = os.path.dirname(path), os.path.basename(path)
- filename = filename.split('.')
- filename, ext = filename[0], '.' + '.'.join(filename[1:])
- if not change_map.get(ext):
- return
- new_ext = change_map[ext]
- old = os.path.join(dirname, filename + ext)
- new = os.path.join(dirname, filename + new_ext)
- shutil.move(old, new)
- return new
- def main(namespace: argparse.Namespace) -> int:
- lite_protobuf_headers = any(out.endswith('.deps.pb.h') for out in namespace.outputs)
- ev_proto = any(out.endswith('.ev.pb.h') for out in namespace.outputs)
- if ev_proto:
- pattern = re.compile(r'proto_h=true:')
- disable_lite_headers = lambda s: re.sub(pattern, '', s)
- namespace.subcommand = [disable_lite_headers(argv) for argv in namespace.subcommand]
- try:
- env = os.environ.copy()
- if lite_protobuf_headers:
- env['PROTOC_PLUGINS_LITE_HEADERS']='1'
- subprocess.check_output(namespace.subcommand, stdin=None, stderr=subprocess.STDOUT, env=env)
- except subprocess.CalledProcessError as e:
- sys.stderr.write(
- '{} returned non-zero exit code {}.\n{}\n'.format(' '.join(e.cmd), e.returncode, e.output.decode('utf-8', errors='ignore'))
- )
- return e.returncode
- if lite_protobuf_headers:
- paths = [strip_file_ext(out) for out in namespace.outputs if out.endswith('.deps.pb.h')]
- proto_h_files = [out + '.proto.h' for out in paths]
- pb_h_files = [out + '.pb.h' for out in paths]
- change_map = {
- '.proto.h': '.pb.h',
- '.pb.h': '.deps.pb.h',
- }
- [change_file_ext(out, change_map) for out in pb_h_files]
- [change_file_ext(out, change_map) for out in proto_h_files]
- for output in namespace.outputs:
- with open(output, 'rt', encoding="utf-8") as f:
- patched_text, num_patches = patch_proto_file(f.read())
- if num_patches:
- with open(output, 'wt', encoding="utf-8") as f:
- f.write(patched_text)
- return 0
- if __name__ == '__main__':
- sys.exit(main(parse_args()))
|