summaryrefslogtreecommitdiff
path: root/create_lts.py
blob: 642b88471e2ebc8c3a19d06a68629545be0c1f30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/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(
      '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/
  ReplaceStringsInFile(
      'CMake/AbseilHelpers.cmake',
      {'SOVERSION 0': 'SOVERSION "{}.0.0"'.format(datestamp[2:6])})
  StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin',
                          '# absl:lts-remove-end')


if __name__ == '__main__':
  main(sys.argv)