| #!/usr/bin/env fuchsia-vendored-python |
| # Copyright 2020 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 json |
| import os |
| import re |
| import subprocess |
| import sys |
| |
| # Golden file build API module. |
| GOLDEN_FILES_JSON = "golden_files.json" |
| |
| DESCRIPTION = """ |
| Reruns golden file checks in the current build, relying on the |
| "golden_files" build API module. That is, unless `--list` is passed, in |
| which case this command only prints out the associated goldens. |
| |
| The goldens may be filtered by a substring of their source path (e.g., a |
| full source-relative directory) or by a regular expression; if no search |
| term is provided, all accessible golden files will be matched. |
| |
| TODO(crbug.com/gn/301): This command may deal in stale metadata. Until this |
| bug is resolved, users must take care to make sure their build metadata is |
| up to data (e.g., via `fx gen`) before invoking this command. |
| """ |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| prog="fx check-goldens", |
| formatter_class=argparse.RawTextHelpFormatter, |
| description=DESCRIPTION, |
| ) |
| parser.add_argument( |
| "--list", |
| help="Whether to just list the goldens instead of updating them", |
| action="store_true", |
| ) |
| parser.add_argument( |
| "--regex", |
| help="if set, the search term will be matched as a regular expression", |
| action="store_true", |
| ) |
| parser.add_argument( |
| "--all", |
| help="if set, includes otherwise ignored, dynamically-specified goldens (i.e., those specified via a build-time manifest)", |
| action="store_true", |
| ) |
| parser.add_argument( |
| "search_term", |
| help="search term to match golden files against", |
| nargs="?", |
| ) |
| args = parser.parse_args() |
| |
| build_dir = os.path.relpath(os.getenv("FUCHSIA_BUILD_DIR")) |
| if build_dir is None: |
| print("FUCHSIA_BUILD_DIR not set") |
| return 1 |
| |
| golden_files_json = os.path.join(build_dir, GOLDEN_FILES_JSON) |
| if not os.path.exists(golden_files_json): |
| subprocess.check_call(["fx", "gen"]) |
| |
| with open(golden_files_json) as f: |
| entries = json.load(f) |
| |
| # Account for comparisons given indirectly via build-time manifests, |
| # ensuring that they are built before proceeding. |
| if args.all: |
| manifests = [] |
| for entry in entries: |
| if "comparison_manifest" in entry: |
| manifests.append(entry["comparison_manifest"]) |
| if manifests: |
| subprocess.check_call(["fx", "build"] + manifests) |
| |
| # Reload `entries`, as the JSON file may have been regenerated. |
| with open(golden_files_json) as f: |
| entries = json.load(f) |
| |
| def is_match(filename): |
| if not args.search_term: |
| return True |
| if args.regex: |
| return re.search(args.search_term, filename) != None |
| return args.search_term in filename |
| |
| stamps = [] |
| matches = [] |
| for entry in entries: |
| comparisons = [] |
| if "comparisons" in entry: |
| comparisons = entry["comparisons"] |
| elif args.all: |
| manifest = os.path.join(build_dir, entry["comparison_manifest"]) |
| with open(manifest) as f: |
| comparisons = json.load(f) |
| |
| matched = False |
| for comparison in comparisons: |
| golden = comparison["golden"] |
| if is_match(golden): |
| matched = True |
| matches.append(golden) |
| if matched: |
| stamps.append(entry["stamp"]) |
| |
| if args.list: |
| print("\n".join(matches)) |
| elif stamps: |
| subprocess.check_call(["fx", "build"] + stamps) |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main()) |