1
+ #!/bin/python3
2
+ #
3
+ # increment_version.py
4
+ #
5
+ # This source file is part of the FoundationDB open source project
6
+ #
7
+ # Copyright 2015-2025 Apple Inc. and the FoundationDB project authors
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+
22
+ import argparse
23
+ import re
24
+ import subprocess
25
+ import sys
26
+
27
+
28
+ VERSION_POSITIONS = ['MAJOR' , 'MINOR' , 'BUILD' , 'PATCH' ]
29
+ VERSION_LINE = re .compile (r'version\s*\=\s*(\d+)\.(\d+)\.(\d+)\.(\d+)' )
30
+
31
+
32
+ def incremented_version (version : (int , int , int , int ), update_type : str ) -> tuple [int , int , int , int ]:
33
+ update_pos = VERSION_POSITIONS .index (update_type )
34
+ new_version = []
35
+ for i in range (len (version )):
36
+ if i < update_pos :
37
+ new_version .append (version [i ])
38
+ elif i == update_pos :
39
+ new_version .append (version [i ] + 1 )
40
+ else :
41
+ new_version .append (0 )
42
+ return tuple (new_version )
43
+
44
+
45
+ def version_string (version : tuple [int , int , int , int ]) -> str :
46
+ return '.' .join (map (str , version ))
47
+
48
+
49
+ def update_version (filename : str , update_type : str ) -> tuple [int , int , int , int ]:
50
+ lines = []
51
+ found = False
52
+ version = None
53
+ new_version = None
54
+ with open (filename , 'r' ) as fin :
55
+ for l in fin :
56
+ m = VERSION_LINE .match (l )
57
+ if m :
58
+ if version is not None :
59
+ raise ValueError ('File contains multiple version lines' )
60
+ version = (int (m .group (1 )), int (m .group (2 )), int (m .group (3 )), int (m .group (4 )))
61
+ new_version = incremented_version (version , update_type )
62
+ lines .append (f'version={ version_string (new_version )} \n ' )
63
+ found = True
64
+ else :
65
+ lines .append (l )
66
+
67
+ if not found :
68
+ raise ValueError (f'Unable to find version in { filename } ' )
69
+
70
+ with open (filename , 'w' ) as fout :
71
+ for l in lines :
72
+ fout .write (l )
73
+ print (f'Update version file { filename } ' )
74
+ return new_version
75
+
76
+
77
+ def main (argv : list [str ]):
78
+ parser = argparse .ArgumentParser (prog = 'increment_version' ,
79
+ description = 'Utility to increment the project version stored in a version file' )
80
+ parser .add_argument ('filename' , type = str , help = 'File containing version to increment' )
81
+ parser .add_argument ('-u' , '--update-type' , type = str , default = 'BUILD' , choices = VERSION_POSITIONS ,
82
+ help = 'Type of update. Determines which position within the build number is updated' )
83
+ parser .add_argument ('-c' , '--commit' , action = 'store_true' , default = False , help = 'Whether to commit the update or not' )
84
+
85
+ args = parser .parse_args (argv )
86
+ new_version = update_version (args .filename , args .update_type )
87
+
88
+ if args .commit :
89
+ subprocess .check_output (['git' , 'add' , args .filename ])
90
+ subprocess .check_output (['git' , 'commit' , '-m' , f'Updating version to { version_string (new_version )} ' ])
91
+ print ('Version update committed' )
92
+
93
+
94
+ if __name__ == '__main__' :
95
+ main (sys .argv [1 :])
0 commit comments