#!/usr/bin/env python3 # # Copyright 2021 The Abseil Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A script to do source transformations to create a new LTS release. Usage: ./create_lts.py YYYYMMDD """ import sys def ReplaceStringsInFile(filename, replacement_dict): """Performs textual replacements in a file. Rewrites filename with the keys in replacement_dict replaced with their values. This function assumes the file can fit in memory. Args: filename: the filename to perform the replacement on replacement_dict: a dictionary of key strings to be replaced with their values Raises: Exception: A failure occurred """ f = open(filename, 'r') content = f.read() f.close() for key, value in replacement_dict.items(): original = content content = content.replace(key, value) if content == original: raise Exception('Failed to find {} in {}'.format(key, filename)) f = open(filename, 'w') f.write(content) f.close() def StripContentBetweenTags(filename, strip_begin_tag, strip_end_tag): """Strip contents from a file. Rewrites filename with by removing all content between strip_begin_tag and strip_end_tag, including the tags themselves. Args: filename: the filename to perform the replacement on strip_begin_tag: the start of the content to be removed strip_end_tag: the end of the content to be removed Raises: Exception: A failure occurred """ f = open(filename, 'r') content = f.read() f.close() while True: begin = content.find(strip_begin_tag) if begin == -1: break end = content.find(strip_end_tag, begin + len(strip_begin_tag)) if end == -1: raise Exception('{}: imbalanced strip begin ({}) and ' 'end ({}) tags'.format(filename, strip_begin_tag, strip_end_tag)) content = content.replace(content[begin:end + len(strip_end_tag)], '') f = open(filename, 'w') f.write(content) f.close() def main(argv): if len(argv) != 2: print('Usage: {} YYYYMMDD'.format(sys.argv[0], file=sys.stderr)) sys.exit(1) datestamp = sys.argv[1] if len(datestamp) != 8 or not datestamp.isdigit(): raise Exception( 'datestamp={} is not in the YYYYMMDD format'.format(datestamp)) # Replacement directives go here. ReplaceStringsInFile( 'MODULE.bazel', { 'version = "head"': 'version = "{}.0"'.format(datestamp) }) ReplaceStringsInFile( 'absl/base/config.h', { '#undef ABSL_LTS_RELEASE_VERSION': '#define ABSL_LTS_RELEASE_VERSION {}'.format(datestamp), '#undef ABSL_LTS_RELEASE_PATCH_LEVEL': '#define ABSL_LTS_RELEASE_PATCH_LEVEL 0' }) ReplaceStringsInFile( 'absl/base/options.h', { '#define ABSL_OPTION_USE_INLINE_NAMESPACE 0': '#define ABSL_OPTION_USE_INLINE_NAMESPACE 1', '#define ABSL_OPTION_INLINE_NAMESPACE_NAME head': '#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_{}'.format( datestamp) }) ReplaceStringsInFile( 'CMakeLists.txt', { 'project(absl LANGUAGES CXX)': ( 'project(absl LANGUAGES CXX VERSION {})'.format(datestamp) ), # Set the SOVERSION to YYMM.0.0 - The first 0 means we only have ABI # compatible changes, and the second 0 means we can increment it to # mark changes as ABI-compatible, for patch releases. Note that we # only use the last two digits of the year and the month because the # MacOS linker requires the first part of the SOVERSION to fit into # 16 bits. # https://www.sicpers.info/2013/03/how-to-version-a-mach-o-library/ 'ABSL_SOVERSION 0': 'ABSL_SOVERSION "{}.0.0"'.format(datestamp[2:6]), }, ) StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin', '# absl:lts-remove-end') if __name__ == '__main__': main(sys.argv)