blob: 458dd32324b95aa182dc61ba2b4046e9acfa200c [file] [log] [blame]
Yu-Ping Wufaec3ab2020-03-27 17:06:10 +08001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-"
3#
4# Copyright 2020 The Chromium OS Authors. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7"""Parse ChangeLog from CPCon and generate commit message.
8
9Usage:
10 1. Copy ChangeLog from CPCon (everything except the MENU bar)
11 2. xsel -b | ./gen_uprev_msg.py [-b BOARD] [--extra-repo-file FILE]
12 3. Commit message will be printed to stdout
13 4. Be aware of the warning messages in stderr
14"""
15from __future__ import print_function
16
17import argparse
18import collections
19import logging
20import re
21import sys
22
23logging.basicConfig(level=logging.INFO)
24logger = logging.getLogger()
25
26MAX_LENGTH = 72
27CHANGES_PATTERN = r'Changes between ([0-9\.]+) and ([0-9\.]+)'
28
29DEFAULT_REPOS = (
30 'src/overlays',
31 'src/platform/bmpblk',
32 'src/platform/depthcharge',
33 'src/platform/ec',
34 'src/platform/firmware',
35 'src/platform/vboot_reference',
36 'src/third_party/arm-trusted-firmware',
37 'src/third_party/chromiumos-overlay',
38 'src/third_party/coreboot',
39 'src/third_party/coreboot/3rdparty/blobs',
40)
41
42
43CL = collections.namedtuple('CL', ['commit', 'cl', 'bug', 'title'])
44
45
46def read_extra_repos(filename):
47 """Read extra repos from |filename|."""
48 repos = set()
49 with open(filename) as f:
50 for line in f:
51 repo = line.strip()
52 if repo:
53 repos.add(repo)
54 return repos
55
56
57def parse_cl(line):
58 """Parse CL."""
59 tokens = line.split('\t')
60 if len(tokens) != 6:
61 return None
62 commit, cl, bug, _date, _author, title = tokens
63 return CL(commit, int(cl) if cl else None, int(bug) if bug else None, title)
64
65
66def main(args):
67 """Parse ChangeLog and print commit message."""
68 parser = argparse.ArgumentParser(description=__doc__)
69 parser.add_argument('-b', '--board')
70 parser.add_argument('--extra-repo-file',
71 help='File containing extra repo names')
72 args = parser.parse_args(args)
73 board = args.board or 'BOARD'
74 included_repos = set(DEFAULT_REPOS)
75 if args.extra_repo_file:
76 included_repos |= read_extra_repos(args.extra_repo_file)
77
78 changes = False
79 repos = []
80 repo = None
81 ignored_repos = []
82 skipped_lines = []
83 for line in sys.stdin:
84 line = line.strip()
85
86 # Parse "Changes between 12573.80.0 and 12573.88.0"
87 if not changes:
88 m = re.match(CHANGES_PATTERN, line)
89 if m:
90 groups = m.groups()
91 if len(groups) == 2:
92 changes = groups
93 continue
94
95 # Parse repo
96 tokens = line.split()
97 if len(tokens) == 1 and '/' in tokens[0]:
98 repo = tokens[0]
99 if repo in included_repos:
100 cl_list = []
101 repos.append((repo, cl_list))
102 else:
103 ignored_repos.append(repo)
104 repo = None
105 continue
106
107 # Parse CL
108 if not repo:
109 continue
110
111 cl = parse_cl(line)
112 if cl:
113 cl_list.append(cl)
114 else:
115 skipped_lines.append(line)
116 continue
117
118 if not repos:
119 logger.error('No repo found from ChangeLog')
120 return 1
121
122 # Output
123 if changes:
124 title = (f'chromeos-firmware-{board}: '
Paul Huang49875c72020-10-30 10:46:25 +0800125 f'Uprev firmware to {changes[1]} for {board}')
Yu-Ping Wufaec3ab2020-03-27 17:06:10 +0800126 print(title)
127 print()
128
129 print(f'Changes between {changes[0]} and {changes[1]}:')
130
131 bugs = set()
132 for repo, cl_list in repos:
133 print()
134 print(repo)
135 private = 'private' in repo
136 for cl in cl_list:
137 if not cl.cl:
138 continue
139 cl_str = f'CL:*{cl.cl}' if private else f'CL:{cl.cl}'
140 title_max_len = MAX_LENGTH - len(cl_str) - 1 - 4
141 title = cl.title
142 while len(title) > title_max_len:
143 tokens = title.rsplit(None, 1)
144 if len(tokens) <= 1:
145 break
146 title = tokens[0]
147 line = f' {cl_str}\t{title}'
148 print(line)
149 if cl.bug:
150 bugs.add(cl.bug)
151
152 print()
153 print('BRANCH=none')
Chen-Tsung Hsiehcd097c82020-10-30 09:35:34 +0800154 bugs = [f'b:{bug}' if bug >= 1e8 else f'chromium:{bug}'
Yu-Ping Wufaec3ab2020-03-27 17:06:10 +0800155 for bug in sorted(bugs)]
156 line_bugs = []
157 length = len('BUG=')
158 for bug in bugs:
159 if line_bugs:
160 bug = ', ' + bug
161 if length + len(bug) <= MAX_LENGTH:
162 line_bugs.append(bug)
163 length += len(bug)
164 else:
165 print('BUG=' + ''.join(line_bugs))
166 line_bugs = []
167 length = 0
168 if line_bugs:
169 print('BUG=' + ''.join(line_bugs))
170 print(f'TEST=emerge-{board} chromeos-firmware-{board}')
171
172 # Warnings
173 for repo in ignored_repos:
174 logger.warning('Ignore repo %s', repo)
175 for line in skipped_lines:
176 logger.warning('Skipping line: %s', line)
177
178
179if __name__ == '__main__':
180 sys.exit(main(sys.argv[1:]))