1#!/usr/bin/env python3 2# 3# See: go/camera-sideline#versions for more context 4# 5# This script generates the apex manifest version number (which is also used for 6# the outer aab/jar object's version available to PackageManager). 7# 8# That version is limited to INT_MAX 9# Strategy: 10# if(local eng build) 11# version = 2147480000 12# else 13# version = brach specific code + padding + numeric part of build number 14# 15# 2147480000 is chosen as being a value that can install over any expected build 16# server build number that is still a little smaller than INT_MAX to leave room 17# for maneuvering 18 19import os 20import re 21import sys 22 23BRANCH_SPECIFIC_VERSION_IDENTIFIER = 3 # sc-v2 24DEFAULT_ENG_BUILD_NUMBER = 2147480000 25DEFAULT_BAD_BUILD_NUMBER = DEFAULT_ENG_BUILD_NUMBER - 1 26 27 28def tame_box(numeric_build_number): 29 # Box the regex extracted value to a min and a max, just in case. Should not 30 # be needed ever. 31 if numeric_build_number < 1: 32 numeric_build_number = 1 33 if numeric_build_number > DEFAULT_ENG_BUILD_NUMBER: 34 numeric_build_number = DEFAULT_BAD_BUILD_NUMBER 35 return numeric_build_number 36 37 38def get_version(input_path, output_path): 39 40 soong_build_number = DEFAULT_BAD_BUILD_NUMBER 41 numeric_build_number = DEFAULT_BAD_BUILD_NUMBER 42 43 # Extract the Android Build ID from the build products 44 out_dir = os.getenv('OUT_DIR') 45 with open('%s/soong/build_number.txt' % out_dir, 'r') as file: 46 soong_build_number = file.read().replace('\n', '') 47 48 # Eng builds all have a default very high version number to permit for local 49 # builds to ovewrite whatever else is installed on the OS. 50 if soong_build_number.startswith('eng.'): # eng.bills.20210901.235403 51 numeric_build_number = DEFAULT_ENG_BUILD_NUMBER 52 else: 53 # We only want the numeric part of the Android Build ID 54 match = re.search(r'([0-9]+)', soong_build_number) 55 if match: 56 numeric_build_number = int(match.group(0)) 57 else: 58 numeric_build_number = DEFAULT_BAD_BUILD_NUMBER 59 60 # Tame the inputs into a reasonable box, just in case 61 numeric_build_number = tame_box(numeric_build_number) 62 # print('numeric_build_number: %s' % str(numeric_build_number)) 63 64 # With the numeric build number as a starting point, let's augment it with 65 # the BRANCH_SPECIFIC_VERSION_IDENTIFIER to differentiate build products from 66 # this branch according to: go/camera-sideline#versions 67 branched_build_number = numeric_build_number 68 if numeric_build_number == DEFAULT_ENG_BUILD_NUMBER: 69 # High default eng numbers can't really be multiplied so we add our branch 70 # specific number instead 71 branched_build_number = numeric_build_number + BRANCH_SPECIFIC_VERSION_IDENTIFIER 72 else: 73 # Two cases to consider: 74 # 1. A "regular" Android Build ID like: 7699287 75 # 2. A pending Android Build ID like: P25748464 76 77 # "It's just string concatenation" 78 string_build_number = '%s%s' % (BRANCH_SPECIFIC_VERSION_IDENTIFIER, 79 str(numeric_build_number).zfill(8)) 80 # Ints in python3 are long 81 branched_build_number = int(string_build_number) 82 # Tame the result into a reasonable box, just in case 83 branched_build_number = tame_box(branched_build_number) 84 85 # print('soong_build_number: %s' % soong_build_number) 86 # print('branched_build_number: %s' % str(branched_build_number)) 87 88 # Bash version: 89 # cat $1 | \ 90 # sed -E "s/\{BUILD_NUMBER\}/$numeric_build_number/g" | \ 91 # sed -E "s/\{BUILD_ID\}/$soong_build_number/g" > $2 92 try: 93 if os.path.exists(input_path): 94 input_fh = open(input_path, 'r') 95 contents = input_fh.readlines() 96 # print('Read: %s' % input_path) 97 new_contents = [] 98 input_fh.close() 99 for line in contents: 100 line = line.replace('{BUILD_ID}', soong_build_number) 101 line = line.replace('{BUILD_NUMBER}', str(branched_build_number)) 102 new_contents.append(line) 103 # print(new_contents) 104 output_fh = open(output_path, 'w') 105 output_fh.write(''.join(new_contents)) 106 output_fh.close() 107 # print('Wrote: %s' % output_path) 108 except IOError: 109 print(f'error occurred trying to read the file {input_path}') 110 return 1 111 112 return 0 113 114 115def main(): 116 return get_version(*sys.argv[1:]) 117 118 119if __name__ == '__main__': 120 sys.exit(main()) 121 122