1*9356374aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*9356374aSAndroid Build Coastguard Worker# 3*9356374aSAndroid Build Coastguard Worker# Copyright 2021 The Abseil Authors. 4*9356374aSAndroid Build Coastguard Worker# 5*9356374aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*9356374aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*9356374aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*9356374aSAndroid Build Coastguard Worker# 9*9356374aSAndroid Build Coastguard Worker# https://www.apache.org/licenses/LICENSE-2.0 10*9356374aSAndroid Build Coastguard Worker# 11*9356374aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*9356374aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*9356374aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*9356374aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*9356374aSAndroid Build Coastguard Worker# limitations under the License. 16*9356374aSAndroid Build Coastguard Worker"""A script to do source transformations to create a new LTS release. 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker Usage: ./create_lts.py YYYYMMDD 19*9356374aSAndroid Build Coastguard Worker""" 20*9356374aSAndroid Build Coastguard Worker 21*9356374aSAndroid Build Coastguard Workerimport sys 22*9356374aSAndroid Build Coastguard Worker 23*9356374aSAndroid Build Coastguard Worker 24*9356374aSAndroid Build Coastguard Workerdef ReplaceStringsInFile(filename, replacement_dict): 25*9356374aSAndroid Build Coastguard Worker """Performs textual replacements in a file. 26*9356374aSAndroid Build Coastguard Worker 27*9356374aSAndroid Build Coastguard Worker Rewrites filename with the keys in replacement_dict replaced with 28*9356374aSAndroid Build Coastguard Worker their values. This function assumes the file can fit in memory. 29*9356374aSAndroid Build Coastguard Worker 30*9356374aSAndroid Build Coastguard Worker Args: 31*9356374aSAndroid Build Coastguard Worker filename: the filename to perform the replacement on 32*9356374aSAndroid Build Coastguard Worker replacement_dict: a dictionary of key strings to be replaced with their 33*9356374aSAndroid Build Coastguard Worker values 34*9356374aSAndroid Build Coastguard Worker 35*9356374aSAndroid Build Coastguard Worker Raises: 36*9356374aSAndroid Build Coastguard Worker Exception: A failure occurred 37*9356374aSAndroid Build Coastguard Worker """ 38*9356374aSAndroid Build Coastguard Worker f = open(filename, 'r') 39*9356374aSAndroid Build Coastguard Worker content = f.read() 40*9356374aSAndroid Build Coastguard Worker f.close() 41*9356374aSAndroid Build Coastguard Worker 42*9356374aSAndroid Build Coastguard Worker for key, value in replacement_dict.items(): 43*9356374aSAndroid Build Coastguard Worker original = content 44*9356374aSAndroid Build Coastguard Worker content = content.replace(key, value) 45*9356374aSAndroid Build Coastguard Worker if content == original: 46*9356374aSAndroid Build Coastguard Worker raise Exception('Failed to find {} in {}'.format(key, filename)) 47*9356374aSAndroid Build Coastguard Worker 48*9356374aSAndroid Build Coastguard Worker f = open(filename, 'w') 49*9356374aSAndroid Build Coastguard Worker f.write(content) 50*9356374aSAndroid Build Coastguard Worker f.close() 51*9356374aSAndroid Build Coastguard Worker 52*9356374aSAndroid Build Coastguard Worker 53*9356374aSAndroid Build Coastguard Workerdef StripContentBetweenTags(filename, strip_begin_tag, strip_end_tag): 54*9356374aSAndroid Build Coastguard Worker """Strip contents from a file. 55*9356374aSAndroid Build Coastguard Worker 56*9356374aSAndroid Build Coastguard Worker Rewrites filename with by removing all content between 57*9356374aSAndroid Build Coastguard Worker strip_begin_tag and strip_end_tag, including the tags themselves. 58*9356374aSAndroid Build Coastguard Worker 59*9356374aSAndroid Build Coastguard Worker Args: 60*9356374aSAndroid Build Coastguard Worker filename: the filename to perform the replacement on 61*9356374aSAndroid Build Coastguard Worker strip_begin_tag: the start of the content to be removed 62*9356374aSAndroid Build Coastguard Worker strip_end_tag: the end of the content to be removed 63*9356374aSAndroid Build Coastguard Worker 64*9356374aSAndroid Build Coastguard Worker Raises: 65*9356374aSAndroid Build Coastguard Worker Exception: A failure occurred 66*9356374aSAndroid Build Coastguard Worker """ 67*9356374aSAndroid Build Coastguard Worker f = open(filename, 'r') 68*9356374aSAndroid Build Coastguard Worker content = f.read() 69*9356374aSAndroid Build Coastguard Worker f.close() 70*9356374aSAndroid Build Coastguard Worker 71*9356374aSAndroid Build Coastguard Worker while True: 72*9356374aSAndroid Build Coastguard Worker begin = content.find(strip_begin_tag) 73*9356374aSAndroid Build Coastguard Worker if begin == -1: 74*9356374aSAndroid Build Coastguard Worker break 75*9356374aSAndroid Build Coastguard Worker end = content.find(strip_end_tag, begin + len(strip_begin_tag)) 76*9356374aSAndroid Build Coastguard Worker if end == -1: 77*9356374aSAndroid Build Coastguard Worker raise Exception('{}: imbalanced strip begin ({}) and ' 78*9356374aSAndroid Build Coastguard Worker 'end ({}) tags'.format(filename, strip_begin_tag, 79*9356374aSAndroid Build Coastguard Worker strip_end_tag)) 80*9356374aSAndroid Build Coastguard Worker content = content.replace(content[begin:end + len(strip_end_tag)], '') 81*9356374aSAndroid Build Coastguard Worker 82*9356374aSAndroid Build Coastguard Worker f = open(filename, 'w') 83*9356374aSAndroid Build Coastguard Worker f.write(content) 84*9356374aSAndroid Build Coastguard Worker f.close() 85*9356374aSAndroid Build Coastguard Worker 86*9356374aSAndroid Build Coastguard Worker 87*9356374aSAndroid Build Coastguard Workerdef main(argv): 88*9356374aSAndroid Build Coastguard Worker if len(argv) != 2: 89*9356374aSAndroid Build Coastguard Worker print('Usage: {} YYYYMMDD'.format(sys.argv[0], file=sys.stderr)) 90*9356374aSAndroid Build Coastguard Worker sys.exit(1) 91*9356374aSAndroid Build Coastguard Worker 92*9356374aSAndroid Build Coastguard Worker datestamp = sys.argv[1] 93*9356374aSAndroid Build Coastguard Worker if len(datestamp) != 8 or not datestamp.isdigit(): 94*9356374aSAndroid Build Coastguard Worker raise Exception( 95*9356374aSAndroid Build Coastguard Worker 'datestamp={} is not in the YYYYMMDD format'.format(datestamp)) 96*9356374aSAndroid Build Coastguard Worker 97*9356374aSAndroid Build Coastguard Worker # Replacement directives go here. 98*9356374aSAndroid Build Coastguard Worker ReplaceStringsInFile( 99*9356374aSAndroid Build Coastguard Worker 'MODULE.bazel', { 100*9356374aSAndroid Build Coastguard Worker 'version = "head"': 101*9356374aSAndroid Build Coastguard Worker 'version = "{}.0"'.format(datestamp) 102*9356374aSAndroid Build Coastguard Worker }) 103*9356374aSAndroid Build Coastguard Worker ReplaceStringsInFile( 104*9356374aSAndroid Build Coastguard Worker 'absl/base/config.h', { 105*9356374aSAndroid Build Coastguard Worker '#undef ABSL_LTS_RELEASE_VERSION': 106*9356374aSAndroid Build Coastguard Worker '#define ABSL_LTS_RELEASE_VERSION {}'.format(datestamp), 107*9356374aSAndroid Build Coastguard Worker '#undef ABSL_LTS_RELEASE_PATCH_LEVEL': 108*9356374aSAndroid Build Coastguard Worker '#define ABSL_LTS_RELEASE_PATCH_LEVEL 0' 109*9356374aSAndroid Build Coastguard Worker }) 110*9356374aSAndroid Build Coastguard Worker ReplaceStringsInFile( 111*9356374aSAndroid Build Coastguard Worker 'absl/base/options.h', { 112*9356374aSAndroid Build Coastguard Worker '#define ABSL_OPTION_USE_INLINE_NAMESPACE 0': 113*9356374aSAndroid Build Coastguard Worker '#define ABSL_OPTION_USE_INLINE_NAMESPACE 1', 114*9356374aSAndroid Build Coastguard Worker '#define ABSL_OPTION_INLINE_NAMESPACE_NAME head': 115*9356374aSAndroid Build Coastguard Worker '#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_{}'.format( 116*9356374aSAndroid Build Coastguard Worker datestamp) 117*9356374aSAndroid Build Coastguard Worker }) 118*9356374aSAndroid Build Coastguard Worker ReplaceStringsInFile( 119*9356374aSAndroid Build Coastguard Worker 'CMakeLists.txt', 120*9356374aSAndroid Build Coastguard Worker { 121*9356374aSAndroid Build Coastguard Worker 'project(absl LANGUAGES CXX)': ( 122*9356374aSAndroid Build Coastguard Worker 'project(absl LANGUAGES CXX VERSION {})'.format(datestamp) 123*9356374aSAndroid Build Coastguard Worker ), 124*9356374aSAndroid Build Coastguard Worker # Set the SOVERSION to YYMM.0.0 - The first 0 means we only have ABI 125*9356374aSAndroid Build Coastguard Worker # compatible changes, and the second 0 means we can increment it to 126*9356374aSAndroid Build Coastguard Worker # mark changes as ABI-compatible, for patch releases. Note that we 127*9356374aSAndroid Build Coastguard Worker # only use the last two digits of the year and the month because the 128*9356374aSAndroid Build Coastguard Worker # MacOS linker requires the first part of the SOVERSION to fit into 129*9356374aSAndroid Build Coastguard Worker # 16 bits. 130*9356374aSAndroid Build Coastguard Worker # https://www.sicpers.info/2013/03/how-to-version-a-mach-o-library/ 131*9356374aSAndroid Build Coastguard Worker 'ABSL_SOVERSION 0': 'ABSL_SOVERSION "{}.0.0"'.format(datestamp[2:6]), 132*9356374aSAndroid Build Coastguard Worker }, 133*9356374aSAndroid Build Coastguard Worker ) 134*9356374aSAndroid Build Coastguard Worker StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin', 135*9356374aSAndroid Build Coastguard Worker '# absl:lts-remove-end') 136*9356374aSAndroid Build Coastguard Worker 137*9356374aSAndroid Build Coastguard Worker 138*9356374aSAndroid Build Coastguard Workerif __name__ == '__main__': 139*9356374aSAndroid Build Coastguard Worker main(sys.argv) 140