VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/GetMaintainer.py@ 105681

最後變更 在這個檔案從105681是 105670,由 vboxsync 提交於 7 月 前

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 7.0 KB
 
1## @file
2# Retrieves the people to request review from on submission of a commit.
3#
4# Copyright (c) 2019, Linaro Ltd. All rights reserved.<BR>
5#
6# SPDX-License-Identifier: BSD-2-Clause-Patent
7#
8
9from __future__ import print_function
10from collections import defaultdict
11from collections import OrderedDict
12import argparse
13import os
14import re
15import SetupGit
16
17EXPRESSIONS = {
18 'exclude': re.compile(r'^X:\s*(?P<exclude>.*?)\r*$'),
19 'file': re.compile(r'^F:\s*(?P<file>.*?)\r*$'),
20 'list': re.compile(r'^L:\s*(?P<list>.*?)\r*$'),
21 'maintainer': re.compile(r'^M:\s*(?P<maintainer>.*?)\r*$'),
22 'reviewer': re.compile(r'^R:\s*(?P<reviewer>.*?)\r*$'),
23 'status': re.compile(r'^S:\s*(?P<status>.*?)\r*$'),
24 'tree': re.compile(r'^T:\s*(?P<tree>.*?)\r*$'),
25 'webpage': re.compile(r'^W:\s*(?P<webpage>.*?)\r*$')
26}
27
28def printsection(section):
29 """Prints out the dictionary describing a Maintainers.txt section."""
30 print('===')
31 for key in section.keys():
32 print("Key: %s" % key)
33 for item in section[key]:
34 print(' %s' % item)
35
36def pattern_to_regex(pattern):
37 """Takes a string containing regular UNIX path wildcards
38 and returns a string suitable for matching with regex."""
39
40 pattern = pattern.replace('.', r'\.')
41 pattern = pattern.replace('?', r'.')
42 pattern = pattern.replace('*', r'.*')
43
44 if pattern.endswith('/'):
45 pattern += r'.*'
46 elif pattern.endswith('.*'):
47 pattern = pattern[:-2]
48 pattern += r'(?!.*?/.*?)'
49
50 return pattern
51
52def path_in_section(path, section):
53 """Returns True of False indicating whether the path is covered by
54 the current section."""
55 if not 'file' in section:
56 return False
57
58 for pattern in section['file']:
59 regex = pattern_to_regex(pattern)
60
61 match = re.match(regex, path)
62 if match:
63 # Check if there is an exclude pattern that applies
64 for pattern in section['exclude']:
65 regex = pattern_to_regex(pattern)
66
67 match = re.match(regex, path)
68 if match:
69 return False
70
71 return True
72
73 return False
74
75def get_section_maintainers(path, section):
76 """Returns a list with email addresses to any M: and R: entries
77 matching the provided path in the provided section."""
78 maintainers = []
79 reviewers = []
80 lists = []
81 nowarn_status = ['Supported', 'Maintained']
82
83 if path_in_section(path, section):
84 for status in section['status']:
85 if status not in nowarn_status:
86 print('WARNING: Maintained status for "%s" is \'%s\'!' % (path, status))
87 for address in section['maintainer']:
88 # Convert to list if necessary
89 if isinstance(address, list):
90 maintainers += address
91 else:
92 maintainers += [address]
93 for address in section['reviewer']:
94 # Convert to list if necessary
95 if isinstance(address, list):
96 reviewers += address
97 else:
98 reviewers += [address]
99 for address in section['list']:
100 # Convert to list if necessary
101 if isinstance(address, list):
102 lists += address
103 else:
104 lists += [address]
105
106 return {'maintainers': maintainers, 'reviewers': reviewers, 'lists': lists}
107
108def get_maintainers(path, sections, level=0):
109 """For 'path', iterates over all sections, returning maintainers
110 for matching ones."""
111 maintainers = []
112 reviewers = []
113 lists = []
114 for section in sections:
115 recipients = get_section_maintainers(path, section)
116 maintainers += recipients['maintainers']
117 reviewers += recipients['reviewers']
118 lists += recipients['lists']
119
120 if not maintainers:
121 # If no match found, look for match for (nonexistent) file
122 # REPO.working_dir/<default>
123 print('"%s": no maintainers found, looking for default' % path)
124 if level == 0:
125 recipients = get_maintainers('<default>', sections, level=level + 1)
126 maintainers += recipients['maintainers']
127 reviewers += recipients['reviewers']
128 lists += recipients['lists']
129 else:
130 print("No <default> maintainers set for project.")
131 if not maintainers:
132 return None
133
134 return {'maintainers': maintainers, 'reviewers': reviewers, 'lists': lists}
135
136def parse_maintainers_line(line):
137 """Parse one line of Maintainers.txt, returning any match group and its key."""
138 for key, expression in EXPRESSIONS.items():
139 match = expression.match(line)
140 if match:
141 return key, match.group(key)
142 return None, None
143
144def parse_maintainers_file(filename):
145 """Parse the Maintainers.txt from top-level of repo and
146 return a list containing dictionaries of all sections."""
147 with open(filename, 'r') as text:
148 line = text.readline()
149 sectionlist = []
150 section = defaultdict(list)
151 while line:
152 key, value = parse_maintainers_line(line)
153 if key and value:
154 section[key].append(value)
155
156 line = text.readline()
157 # If end of section (end of file, or non-tag line encountered)...
158 if not key or not value or not line:
159 # ...if non-empty, append section to list.
160 if section:
161 sectionlist.append(section.copy())
162 section.clear()
163
164 return sectionlist
165
166def get_modified_files(repo, args):
167 """Returns a list of the files modified by the commit specified in 'args'."""
168 commit = repo.commit(args.commit)
169 return commit.stats.files
170
171if __name__ == '__main__':
172 PARSER = argparse.ArgumentParser(
173 description='Retrieves information on who to cc for review on a given commit')
174 PARSER.add_argument('commit',
175 action="store",
176 help='git revision to examine (default: HEAD)',
177 nargs='?',
178 default='HEAD')
179 PARSER.add_argument('-l', '--lookup',
180 help='Find section matches for path LOOKUP',
181 required=False)
182 ARGS = PARSER.parse_args()
183
184 REPO = SetupGit.locate_repo()
185
186 CONFIG_FILE = os.path.join(REPO.working_dir, 'Maintainers.txt')
187
188 SECTIONS = parse_maintainers_file(CONFIG_FILE)
189
190 if ARGS.lookup:
191 FILES = [ARGS.lookup.replace('\\','/')]
192 else:
193 FILES = get_modified_files(REPO, ARGS)
194
195 # Accumulate a sorted list of addresses
196 ADDRESSES = set([])
197 for file in FILES:
198 print(file)
199 recipients = get_maintainers(file, SECTIONS)
200 ADDRESSES |= set(recipients['maintainers'] + recipients['reviewers'] + recipients['lists'])
201 ADDRESSES = list(ADDRESSES)
202 ADDRESSES.sort()
203
204 for address in ADDRESSES:
205 if '<' in address and '>' in address:
206 address = address.split('>', 1)[0] + '>'
207 print(' %s' % address)
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette