1#!/usr/bin/env python3 2# Copyright (C) 2023 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import argparse 17import os 18import re 19import sys 20 21def read_status_file(filepath): 22 result = {} 23 with open(filepath) as f: 24 for line in f: 25 if not line.strip(): 26 continue 27 if line.endswith('\r\n'): 28 line = line.removesuffix('\r\n') 29 else: 30 line = line.removesuffix('\n') 31 var, value = line.split(' ', maxsplit=1) 32 result[var] = value 33 return result 34 35 36def cat(args): 37 status_file = read_status_file(args.file) 38 if args.variable not in status_file: 39 sys.exit(f'error: {args.variable} was not found in {args.file}') 40 print(status_file[args.variable]) 41 42 43def replace(args): 44 status_file = read_status_file(args.file) 45 46 if args.var: 47 trimmed_status_file = {} 48 for var in args.var: 49 if var not in status_file: 50 sys.exit(f'error: {var} was not found in {args.file}') 51 trimmed_status_file[var] = status_file[var] 52 status_file = trimmed_status_file 53 54 pattern = re.compile("|".join([re.escape("{" + v + "}") for v in status_file.keys()])) 55 56 with open(args.input) as inf, open(args.output, 'w') as outf: 57 contents = inf.read() 58 contents = pattern.sub(lambda m: status_file[m.group(0)[1:-1]], contents) 59 outf.write(contents) 60 61 62def main(): 63 parser = argparse.ArgumentParser(description = 'A utility tool for reading the bazel version file. (ctx.version_file, aka volatile-status.txt)') 64 subparsers = parser.add_subparsers(required=True) 65 cat_parser = subparsers.add_parser('cat', description = 'print the value of a single variable in the version file') 66 cat_parser.add_argument('file', help = 'path to the volatile-status.txt file') 67 cat_parser.add_argument('variable', help = 'the variable to print') 68 cat_parser.set_defaults(func=cat) 69 replace_parser = subparsers.add_parser('replace', description = 'Replace strings like {VAR_NAME} in an input file') 70 replace_parser.add_argument('file', help = 'path to the volatile-status.txt file') 71 replace_parser.add_argument('input', help = 'path to the input file with {VAR_NAME} strings') 72 replace_parser.add_argument('output', help = 'path to the output file') 73 replace_parser.add_argument('--var', nargs='*', help = 'If given, only replace these variables') 74 replace_parser.set_defaults(func=replace) 75 args = parser.parse_args() 76 77 args.func(args) 78 79 80if __name__ == '__main__': 81 try: 82 main() 83 except FileNotFoundError as e: 84 # Don't show a backtrace for FileNotFoundErrors 85 sys.exit(str(e)) 86