blob: 447772c0e34fb76d85cd2c96d4400dbc18dc375a [file] [log] [blame]
Hao Nguyen9349e232018-12-14 15:05:48 -08001#!/usr/bin/env python
Hao Nguyene22907f2019-02-20 11:25:39 -08002# Usage: ./update_version.py <MAJOR>.<MINOR>.<MICRO> [<RC version>]
3#
4# Example:
5# ./update_version.py 3.7.1 2
6# => Version will become 3.7.1-rc-2 (beta)
7# ./update_version.py 3.7.1
8# => Version will become 3.7.1 (stable)
Hao Nguyen9349e232018-12-14 15:05:48 -08009
10import datetime
11import re
12import sys
13from xml.dom import minidom
14
Hao Nguyene22907f2019-02-20 11:25:39 -080015if len(sys.argv) < 2 or len(sys.argv) > 3:
Hao Nguyen9349e232018-12-14 15:05:48 -080016 print """
17[ERROR] Please specify a version.
18
Hao Nguyene22907f2019-02-20 11:25:39 -080019./update_version.py <MAJOR>.<MINOR>.<MICRO> [<RC version>]
20
Hao Nguyen9349e232018-12-14 15:05:48 -080021Example:
Hao Nguyene22907f2019-02-20 11:25:39 -080022./update_version.py 3.7.1 2
Hao Nguyen9349e232018-12-14 15:05:48 -080023"""
24 exit(1)
25
26NEW_VERSION = sys.argv[1]
Jie Luo2a465792019-09-18 13:30:03 -070027NEW_VERSION_INFO = [int(x) for x in NEW_VERSION.split('.')]
Hao Nguyen9349e232018-12-14 15:05:48 -080028if len(NEW_VERSION_INFO) != 3:
29 print """
30[ERROR] Version must be in the format <MAJOR>.<MINOR>.<MICRO>
31
32Example:
Hao Nguyene22907f2019-02-20 11:25:39 -080033./update_version.py 3.7.3
Hao Nguyen9349e232018-12-14 15:05:48 -080034"""
35 exit(1)
36
Jie Luo2a465792019-09-18 13:30:03 -070037RC_VERSION = -1
Hao Nguyene22907f2019-02-20 11:25:39 -080038if len(sys.argv) > 2:
39 RC_VERSION = int(sys.argv[2])
40
Hao Nguyen9349e232018-12-14 15:05:48 -080041
42def Find(elem, tagname):
43 for child in elem.childNodes:
44 if child.nodeName == tagname:
45 return child
46 return None
47
48
49def FindAndClone(elem, tagname):
50 return Find(elem, tagname).cloneNode(True)
51
52
53def ReplaceText(elem, text):
54 elem.firstChild.replaceWholeText(text)
55
56
Hao Nguyene22907f2019-02-20 11:25:39 -080057def GetFullVersion(rc_suffix = '-rc-'):
Jie Luo2a465792019-09-18 13:30:03 -070058 if RC_VERSION < 0:
Hao Nguyene22907f2019-02-20 11:25:39 -080059 return NEW_VERSION
60 else:
61 return '%s%s%s' % (NEW_VERSION, rc_suffix, RC_VERSION)
62
63
Hao Nguyen9349e232018-12-14 15:05:48 -080064def RewriteXml(filename, rewriter, add_xml_prefix=True):
65 document = minidom.parse(filename)
66 rewriter(document)
67 # document.toxml() always prepend the XML version without inserting new line.
68 # We wants to preserve as much of the original formatting as possible, so we
69 # will remove the default XML version and replace it with our custom one when
70 # whever necessary.
71 content = document.toxml().replace('<?xml version="1.0" ?>', '')
72 file_handle = open(filename, 'wb')
73 if add_xml_prefix:
74 file_handle.write('<?xml version="1.0" encoding="UTF-8"?>\n')
75 file_handle.write(content)
Hao Nguyen4b02f652018-12-14 15:10:11 -080076 file_handle.write('\n')
Hao Nguyen9349e232018-12-14 15:05:48 -080077 file_handle.close()
78
79
80def RewriteTextFile(filename, line_rewriter):
81 lines = open(filename, 'r').readlines()
82 updated_lines = []
83 for line in lines:
84 updated_lines.append(line_rewriter(line))
85 if lines == updated_lines:
86 print '%s was not updated. Please double check.' % filename
87 f = open(filename, 'w')
88 f.write(''.join(updated_lines))
89 f.close()
90
91
92def UpdateConfigure():
93 RewriteTextFile('configure.ac',
94 lambda line : re.sub(
95 r'^AC_INIT\(\[Protocol Buffers\],\[.*\],\[protobuf@googlegroups.com\],\[protobuf\]\)$',
96 ('AC_INIT([Protocol Buffers],[%s],[protobuf@googlegroups.com],[protobuf])'
Hao Nguyene22907f2019-02-20 11:25:39 -080097 % GetFullVersion()),
Hao Nguyen9349e232018-12-14 15:05:48 -080098 line))
99
100
101def UpdateCpp():
Jie Luo2a465792019-09-18 13:30:03 -0700102 cpp_version = '%d%03d%03d' % (
Hao Nguyen9349e232018-12-14 15:05:48 -0800103 NEW_VERSION_INFO[0], NEW_VERSION_INFO[1], NEW_VERSION_INFO[2])
Adam Cozzette6da79e92020-08-19 11:32:03 -0700104 version_suffix = ''
105 if RC_VERSION != -1:
106 version_suffix = '-rc%s' % RC_VERSION
Paul Yang6973c3a2019-03-26 09:30:12 -0700107 def RewriteCommon(line):
Hao Nguyen9349e232018-12-14 15:05:48 -0800108 line = re.sub(
109 r'^#define GOOGLE_PROTOBUF_VERSION .*$',
110 '#define GOOGLE_PROTOBUF_VERSION %s' % cpp_version,
111 line)
Hao Nguyenc70643e2019-01-24 11:42:45 -0800112 line = re.sub(
113 r'^#define PROTOBUF_VERSION .*$',
114 '#define PROTOBUF_VERSION %s' % cpp_version,
115 line)
Adam Cozzette6da79e92020-08-19 11:32:03 -0700116 line = re.sub(
117 r'^#define GOOGLE_PROTOBUF_VERSION_SUFFIX .*$',
118 '#define GOOGLE_PROTOBUF_VERSION_SUFFIX "%s"' % version_suffix,
119 line)
120 line = re.sub(
121 r'^#define PROTOBUF_VERSION_SUFFIX .*$',
122 '#define PROTOBUF_VERSION_SUFFIX "%s"' % version_suffix,
123 line)
Jie Luo2a465792019-09-18 13:30:03 -0700124 if NEW_VERSION_INFO[2] == 0:
Hao Nguyen9349e232018-12-14 15:05:48 -0800125 line = re.sub(
Hao Nguyenc70643e2019-01-24 11:42:45 -0800126 r'^#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC .*$',
127 '#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC %s' % cpp_version,
128 line)
129 line = re.sub(
Hao Nguyen9349e232018-12-14 15:05:48 -0800130 r'^#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION .*$',
131 '#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION %s' % cpp_version,
132 line)
133 line = re.sub(
134 r'^static const int kMinHeaderVersionForLibrary = .*$',
135 'static const int kMinHeaderVersionForLibrary = %s;' % cpp_version,
136 line)
137 line = re.sub(
138 r'^static const int kMinHeaderVersionForProtoc = .*$',
139 'static const int kMinHeaderVersionForProtoc = %s;' % cpp_version,
140 line)
141 return line
Adam Cozzette6da79e92020-08-19 11:32:03 -0700142
Paul Yang6973c3a2019-03-26 09:30:12 -0700143 def RewritePortDef(line):
144 line = re.sub(
145 r'^#define PROTOBUF_VERSION .*$',
146 '#define PROTOBUF_VERSION %s' % cpp_version,
147 line)
Adam Cozzette6da79e92020-08-19 11:32:03 -0700148 line = re.sub(
149 r'^#define PROTOBUF_VERSION_SUFFIX .*$',
150 '#define PROTOBUF_VERSION_SUFFIX "%s"' % version_suffix,
151 line)
Jie Luo2a465792019-09-18 13:30:03 -0700152 if NEW_VERSION_INFO[2] == 0:
Paul Yang6973c3a2019-03-26 09:30:12 -0700153 line = re.sub(
154 r'^#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC .*$',
155 '#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC %s' % cpp_version,
156 line)
157 line = re.sub(
158 r'^#define PROTOBUF_MIN_PROTOC_VERSION .*$',
159 '#define PROTOBUF_MIN_PROTOC_VERSION %s' % cpp_version,
160 line)
161 line = re.sub(
162 r'^#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION .*$',
163 '#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION %s' % cpp_version,
164 line)
165 return line
Jie Luo43156772019-08-09 13:21:18 -0700166
Jie Luo2a465792019-09-18 13:30:03 -0700167 def RewritePbH(line):
168 line = re.sub(
169 r'^#if PROTOBUF_VERSION < .*$',
170 '#if PROTOBUF_VERSION < %s' % cpp_version,
171 line)
172 line = re.sub(
173 r'^#if .* < PROTOBUF_MIN_PROTOC_VERSION$',
174 '#if %s < PROTOBUF_MIN_PROTOC_VERSION' % cpp_version,
175 line)
176 return line
177
Paul Yang6973c3a2019-03-26 09:30:12 -0700178 RewriteTextFile('src/google/protobuf/stubs/common.h', RewriteCommon)
179 RewriteTextFile('src/google/protobuf/port_def.inc', RewritePortDef)
Jie Luo2a465792019-09-18 13:30:03 -0700180 RewriteTextFile('src/google/protobuf/any.pb.h', RewritePbH)
181 RewriteTextFile('src/google/protobuf/api.pb.h', RewritePbH)
182 RewriteTextFile('src/google/protobuf/descriptor.pb.h', RewritePbH)
183 RewriteTextFile('src/google/protobuf/duration.pb.h', RewritePbH)
184 RewriteTextFile('src/google/protobuf/empty.pb.h', RewritePbH)
185 RewriteTextFile('src/google/protobuf/field_mask.pb.h', RewritePbH)
186 RewriteTextFile('src/google/protobuf/source_context.pb.h', RewritePbH)
187 RewriteTextFile('src/google/protobuf/struct.pb.h', RewritePbH)
188 RewriteTextFile('src/google/protobuf/timestamp.pb.h', RewritePbH)
189 RewriteTextFile('src/google/protobuf/type.pb.h', RewritePbH)
190 RewriteTextFile('src/google/protobuf/wrappers.pb.h', RewritePbH)
191 RewriteTextFile('src/google/protobuf/compiler/plugin.pb.h', RewritePbH)
Hao Nguyen9349e232018-12-14 15:05:48 -0800192
193
194def UpdateCsharp():
195 RewriteXml('csharp/src/Google.Protobuf/Google.Protobuf.csproj',
196 lambda document : ReplaceText(
197 Find(Find(document.documentElement, 'PropertyGroup'), 'VersionPrefix'),
Hao Nguyenfdfe7612019-05-09 06:14:32 -0700198 GetFullVersion(rc_suffix = '-rc')),
Hao Nguyen9349e232018-12-14 15:05:48 -0800199 add_xml_prefix=False)
200
201 RewriteXml('csharp/Google.Protobuf.Tools.nuspec',
202 lambda document : ReplaceText(
203 Find(Find(document.documentElement, 'metadata'), 'version'),
Hao Nguyenfdfe7612019-05-09 06:14:32 -0700204 GetFullVersion(rc_suffix = '-rc')))
Hao Nguyen9349e232018-12-14 15:05:48 -0800205
206
207def UpdateJava():
208 RewriteXml('java/pom.xml',
209 lambda document : ReplaceText(
Hao Nguyene22907f2019-02-20 11:25:39 -0800210 Find(document.documentElement, 'version'), GetFullVersion()))
Hao Nguyen9349e232018-12-14 15:05:48 -0800211
Hao Nguyenc70643e2019-01-24 11:42:45 -0800212 RewriteXml('java/bom/pom.xml',
213 lambda document : ReplaceText(
Hao Nguyene22907f2019-02-20 11:25:39 -0800214 Find(document.documentElement, 'version'), GetFullVersion()))
Hao Nguyenc70643e2019-01-24 11:42:45 -0800215
Hao Nguyen9349e232018-12-14 15:05:48 -0800216 RewriteXml('java/core/pom.xml',
217 lambda document : ReplaceText(
218 Find(Find(document.documentElement, 'parent'), 'version'),
Hao Nguyene22907f2019-02-20 11:25:39 -0800219 GetFullVersion()))
Hao Nguyen9349e232018-12-14 15:05:48 -0800220
Hao Nguyen13e188f2019-04-23 17:06:40 -0700221 RewriteXml('java/lite/pom.xml',
222 lambda document : ReplaceText(
223 Find(Find(document.documentElement, 'parent'), 'version'),
224 GetFullVersion()))
225
Hao Nguyen9349e232018-12-14 15:05:48 -0800226 RewriteXml('java/util/pom.xml',
227 lambda document : ReplaceText(
228 Find(Find(document.documentElement, 'parent'), 'version'),
Hao Nguyene22907f2019-02-20 11:25:39 -0800229 GetFullVersion()))
Hao Nguyen9349e232018-12-14 15:05:48 -0800230
Adam Cozzettef807c022021-05-10 15:31:35 -0700231 RewriteXml('java/kotlin/pom.xml',
232 lambda document : ReplaceText(
233 Find(Find(document.documentElement, 'parent'), 'version'),
234 GetFullVersion()))
235
236 RewriteXml('java/kotlin-lite/pom.xml',
237 lambda document : ReplaceText(
238 Find(Find(document.documentElement, 'parent'), 'version'),
239 GetFullVersion()))
240
Hao Nguyen9349e232018-12-14 15:05:48 -0800241 RewriteXml('protoc-artifacts/pom.xml',
242 lambda document : ReplaceText(
Hao Nguyene22907f2019-02-20 11:25:39 -0800243 Find(document.documentElement, 'version'), GetFullVersion()))
Hao Nguyen9349e232018-12-14 15:05:48 -0800244
245
246def UpdateJavaScript():
247 RewriteTextFile('js/package.json',
248 lambda line : re.sub(
249 r'^ "version": ".*",$',
Hao Nguyene22907f2019-02-20 11:25:39 -0800250 ' "version": "%s",' % GetFullVersion(rc_suffix = '-rc.'),
Hao Nguyen9349e232018-12-14 15:05:48 -0800251 line))
252
253
254def UpdateMakefile():
255 protobuf_version_offset = 11
Jie Luo2a465792019-09-18 13:30:03 -0700256 expected_major_version = 3
Hao Nguyen9349e232018-12-14 15:05:48 -0800257 if NEW_VERSION_INFO[0] != expected_major_version:
258 print """[ERROR] Major protobuf version has changed. Please update
259update_version.py to readjust the protobuf_version_offset and
260expected_major_version such that the PROTOBUF_VERSION in src/Makefile.am is
261always increasing.
262 """
263 exit(1)
264
Jie Luo2a465792019-09-18 13:30:03 -0700265 protobuf_version_info = '%d:%d:0' % (
266 NEW_VERSION_INFO[1] + protobuf_version_offset, NEW_VERSION_INFO[2])
Hao Nguyen9349e232018-12-14 15:05:48 -0800267 RewriteTextFile('src/Makefile.am',
268 lambda line : re.sub(
269 r'^PROTOBUF_VERSION = .*$',
270 'PROTOBUF_VERSION = %s' % protobuf_version_info,
271 line))
272
273
274def UpdateObjectiveC():
275 RewriteTextFile('Protobuf.podspec',
276 lambda line : re.sub(
277 r"^ s.version = '.*'$",
Paul Yang65fed3f2019-05-08 19:15:20 -0700278 " s.version = '%s'" % GetFullVersion(rc_suffix = '-rc'),
Hao Nguyen9349e232018-12-14 15:05:48 -0800279 line))
rmstar2c76c2c2019-07-23 13:51:21 -0700280 RewriteTextFile('Protobuf-C++.podspec',
281 lambda line : re.sub(
282 r"^ s.version = '.*'$",
283 " s.version = '%s'" % GetFullVersion(rc_suffix = '-rc'),
284 line))
Hao Nguyen9349e232018-12-14 15:05:48 -0800285
286
287def UpdatePhp():
288 def Callback(document):
289 def CreateNode(tagname, indent, children):
290 elem = document.createElement(tagname)
291 indent += 1
292 for child in children:
293 elem.appendChild(document.createTextNode('\n' + (' ' * indent)))
294 elem.appendChild(child)
295 indent -= 1
296 elem.appendChild(document.createTextNode('\n' + (' ' * indent)))
297 return elem
298
299 root = document.documentElement
Paul Yang5d8cd3b2019-02-25 15:13:59 -0800300 now = datetime.datetime.now()
301 ReplaceText(Find(root, 'date'), now.strftime('%Y-%m-%d'))
302 ReplaceText(Find(root, 'time'), now.strftime('%H:%M:%S'))
Hao Nguyen9349e232018-12-14 15:05:48 -0800303 version = Find(root, 'version')
Hao Nguyene22907f2019-02-20 11:25:39 -0800304 ReplaceText(Find(version, 'release'), GetFullVersion(rc_suffix = 'RC'))
Hao Nguyen9349e232018-12-14 15:05:48 -0800305 ReplaceText(Find(version, 'api'), NEW_VERSION)
Hao Nguyene22907f2019-02-20 11:25:39 -0800306 stability = Find(root, 'stability')
Bo Yangb52754b2019-02-22 11:31:48 -0800307 ReplaceText(Find(stability, 'release'),
Jie Luo2a465792019-09-18 13:30:03 -0700308 'stable' if RC_VERSION < 0 else 'beta')
309 ReplaceText(Find(stability, 'api'), 'stable' if RC_VERSION < 0 else 'beta')
Hao Nguyen9349e232018-12-14 15:05:48 -0800310 changelog = Find(root, 'changelog')
311 for old_version in changelog.getElementsByTagName('version'):
312 if Find(old_version, 'release').firstChild.nodeValue == NEW_VERSION:
313 print ('[WARNING] Version %s already exists in the change log.'
314 % NEW_VERSION)
315 return
Jie Luo2a465792019-09-18 13:30:03 -0700316 if RC_VERSION != 0:
317 changelog.appendChild(document.createTextNode(' '))
318 release = CreateNode('release', 2, [
319 CreateNode('version', 3, [
320 FindAndClone(version, 'release'),
321 FindAndClone(version, 'api')
322 ]),
323 CreateNode('stability', 3, [
324 FindAndClone(stability, 'release'),
325 FindAndClone(stability, 'api')
326 ]),
327 FindAndClone(root, 'date'),
328 FindAndClone(root, 'time'),
329 FindAndClone(root, 'license'),
Adam Cozzette1b188332020-08-21 11:12:57 -0700330 CreateNode('notes', 3, []),
Jie Luo2a465792019-09-18 13:30:03 -0700331 ])
332 changelog.appendChild(release)
333 changelog.appendChild(document.createTextNode('\n '))
Hao Nguyen9349e232018-12-14 15:05:48 -0800334 RewriteXml('php/ext/google/protobuf/package.xml', Callback)
Paul Yangc7b33922019-02-19 15:54:45 -0800335 RewriteTextFile('php/ext/google/protobuf/protobuf.h',
336 lambda line : re.sub(
337 r'PHP_PROTOBUF_VERSION ".*"$',
338 'PHP_PROTOBUF_VERSION "%s"' % NEW_VERSION,
339 line))
Hao Nguyen9349e232018-12-14 15:05:48 -0800340
Hao Nguyen05f57122019-02-20 11:25:39 -0800341 RewriteTextFile('php/ext/google/protobuf/protobuf.h',
342 lambda line : re.sub(
343 r"^#define PHP_PROTOBUF_VERSION .*$",
344 "#define PHP_PROTOBUF_VERSION \"%s\"" % GetFullVersion(rc_suffix = 'RC'),
345 line))
Hao Nguyen9349e232018-12-14 15:05:48 -0800346
Hao Nguyene22907f2019-02-20 11:25:39 -0800347 RewriteTextFile('php/ext/google/protobuf/protobuf.h',
348 lambda line : re.sub(
349 r"^#define PHP_PROTOBUF_VERSION .*$",
350 "#define PHP_PROTOBUF_VERSION \"%s\"" % GetFullVersion(rc_suffix = 'RC'),
351 line))
352
Hao Nguyen9349e232018-12-14 15:05:48 -0800353def UpdatePython():
354 RewriteTextFile('python/google/protobuf/__init__.py',
355 lambda line : re.sub(
356 r"^__version__ = '.*'$",
Hao Nguyene22907f2019-02-20 11:25:39 -0800357 "__version__ = '%s'" % GetFullVersion(rc_suffix = 'rc'),
Hao Nguyen9349e232018-12-14 15:05:48 -0800358 line))
359
360def UpdateRuby():
361 RewriteTextFile('ruby/google-protobuf.gemspec',
362 lambda line : re.sub(
363 r'^ s.version = ".*"$',
Hao Nguyene22907f2019-02-20 11:25:39 -0800364 ' s.version = "%s"' % GetFullVersion(rc_suffix = '.rc.'),
Hao Nguyen9349e232018-12-14 15:05:48 -0800365 line))
366
367
368UpdateConfigure()
369UpdateCsharp()
370UpdateCpp()
371UpdateJava()
372UpdateJavaScript()
373UpdateMakefile()
374UpdateObjectiveC()
375UpdatePhp()
376UpdatePython()
377UpdateRuby()