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