post_version.py: fix branch name construction for release candidates
[mesa.git] / bin / post_version.py
1 #!/usr/bin/env python3
2 # Copyright © 2019-2020 Intel Corporation
3
4 # Permission is hereby granted, free of charge, to any person obtaining a copy
5 # of this software and associated documentation files (the "Software"), to deal
6 # in the Software without restriction, including without limitation the rights
7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 # copies of the Software, and to permit persons to whom the Software is
9 # furnished to do so, subject to the following conditions:
10
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
13
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 # SOFTWARE.
21
22 """Update the main page, release notes, and calendar."""
23
24 import argparse
25 import calendar
26 import datetime
27 import pathlib
28 import subprocess
29
30 from lxml import (
31 etree,
32 html,
33 )
34
35
36 def is_point_release(version: str) -> bool:
37 return not version.endswith('.0')
38
39
40 def is_release_candidate(version: str) -> bool:
41 return '-rc' in version
42
43
44 def branch_name(version: str) -> str:
45 if is_release_candidate(version):
46 version = version.split('-')[0]
47 (major, minor, _) = version.split('.')
48 return f'{major}.{minor}'
49
50
51 def update_index(is_point: bool, version: str) -> None:
52 p = pathlib.Path(__file__).parent.parent / 'docs' / 'index.html'
53 with p.open('rt') as f:
54 tree = html.parse(f)
55
56 news = tree.xpath('.//h1')[0]
57
58 date = datetime.date.today()
59 month = calendar.month_name[date.month]
60 header = etree.Element('h2')
61 header.text = f"{month} {date.day}, {date.year}"
62
63 body = etree.Element('p')
64 a = etree.SubElement(
65 body, 'a', attrib={'href': f'relnotes/{version}.html'})
66 a.text = f"Mesa {version}"
67 if is_point:
68 a.tail = " is released. This is a bug fix release."
69 else:
70 a.tail = (" is released. This is a new development release. "
71 "See the release notes for more information about this release.")
72
73 root = news.getparent()
74 index = root.index(news) + 1
75 root.insert(index, body)
76 root.insert(index, header)
77
78 tree.write(p.as_posix(), method='html', pretty_print=True)
79 subprocess.run(['git', 'add', p])
80
81
82 def update_release_notes(version: str) -> None:
83 p = pathlib.Path(__file__).parent.parent / 'docs' / 'relnotes.html'
84 with p.open('rt') as f:
85 tree = html.parse(f)
86
87 li = etree.Element('li')
88 a = etree.SubElement(li, 'a', href=f'relnotes/{version}.html')
89 a.text = f'{version} release notes'
90
91 ul = tree.xpath('.//ul')[0]
92 ul.insert(0, li)
93
94 tree.write(p.as_posix(), method='html', pretty_print=True)
95 subprocess.run(['git', 'add', p])
96
97
98 def update_calendar(version: str) -> None:
99 p = pathlib.Path(__file__).parent.parent / 'docs' / 'release-calendar.html'
100 with p.open('rt') as f:
101 tree = html.parse(f)
102
103 branch = branch_name(version)
104
105 old = None
106 new = None
107
108 for tr in tree.xpath('.//tr'):
109 if old is not None:
110 new = tr
111 break
112
113 for td in tr.xpath('./td'):
114 if td.text == branch:
115 old = tr
116 break
117
118 assert old is not None
119 assert new is not None
120 old.getparent().remove(old)
121
122 # rowspan is 1 based in html, but 0 based in lxml
123 rowspan = int(td.get("rowspan")) - 1
124 if rowspan:
125 td.set("rowspan", str(rowspan))
126 new.insert(0, td)
127
128 tree.write(p.as_posix(), method='html', pretty_print=True)
129 subprocess.run(['git', 'add', p])
130
131
132 def main() -> None:
133 parser = argparse.ArgumentParser()
134 parser.add_argument('version', help="The released version.")
135 args = parser.parse_args()
136
137 is_point = is_point_release(args.version)
138
139 update_index(is_point, args.version)
140 update_release_notes(args.version)
141 update_calendar(args.version)
142 subprocess.run(['git', 'commit', '-m',
143 'docs: update calendar, add news item, and link releases '
144 f'notes for {args.version}'])
145
146
147 if __name__ == "__main__":
148 main()