blob: 3077f928c3c6a1f67ae359a9476665cd21d9b4a0 [file] [log] [blame]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import os
import re
import shutil
import sys
# Verifies that the candidate golden go proto file matches the provided golden.
# Intentionally ignores the version numbers of the protoc compiler and plugins
# that are embedded in the files.
MISMATCH_MSG = '''\
Error: Golden file mismatch! To print the differences, run:
diff -urN {candidate_path} {golden_path}
To acknowledge this change, please run:
cp {candidate_path} {golden_path}
'''
def filter_line(line):
"""Filter input .pb.go line to ignore non-problematic differences."""
# Strip the compiler and plugin version numbers.
#
# protoc-gen-go generates:
#
# // <tab>protoc-gen-go v1.26.0\n
# // <tab>protoc v3.12.4\n
#
# protoc-gen-go-grpc generates:
#
# // - protoc-gen-go v1.26.0\n
# // - protoc v3.12.4\n
#
# Note that protoc-gen-go-grpc does not embed its version number
# in its output, so isn't checked here.
for version_prefix in (
'// \tprotoc ',
'// \tprotoc-gen-go ',
'// - protoc ',
'// - protoc-gen-go-grpc ',
):
if line.startswith(version_prefix):
return version_prefix + '\n'
# Ignore differences in whitespace within comments. For example, the
# following lines are treated as the same:
#
# someCode() // - foo bar baz
# someCode() // - foo bar baz
# someCode() //- foo bar baz
comment_match = re.match(r'^(.*\/\/)(\s*)(.*)$', line)
if comment_match is not None:
return (
comment_match.group(1) +
re.sub(r'\s+', ' ', comment_match.group(3)))
return line
def read_file(path):
"""Read input .pb.go file into a list of filtered lines."""
with open(path) as f:
return [filter_line(l) for l in f.readlines()]
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--golden', help='Path to the golden file', required=True)
parser.add_argument(
'--candidate', help='Path to the local file', required=True)
parser.add_argument(
'--fuchsia-dir', help='Path to Fuchsia source directory')
parser.add_argument(
'--stamp', help='Path to the victory file', required=True)
parser.add_argument(
'--update',
help="Overwrites candidate with golden if they don't match.",
action='store_true')
args = parser.parse_args()
golden = read_file(args.golden)
candidate = read_file(args.candidate)
if golden != candidate:
if args.update:
shutil.copyfile(args.candidate, args.golden)
else:
# Compute paths relative to the Fuchsia directory for the message
# below.
fuchsia_dir = args.fuchsia_dir if args.fuchsia_dir else '../..'
fuchsia_dir = os.path.abspath(fuchsia_dir)
golden_path = os.path.relpath(args.golden, fuchsia_dir)
candidate_path = os.path.relpath(args.candidate, fuchsia_dir)
print(
MISMATCH_MSG.format(
candidate_path=candidate_path, golden_path=golden_path),
file=sys.stderr)
return 1
with open(args.stamp, 'w') as stamp_file:
stamp_file.write('Golden!\n')
return 0
if __name__ == '__main__':
sys.exit(main())