BaseTools/Scripts: Fix GetMaintainer.py line endings

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
This commit is contained in:
Michael D Kinney
2021-07-07 16:58:52 -07:00
committed by mergify[bot]
parent 391cffcb61
commit 8781b143de

View File

@ -1,194 +1,194 @@
## @file ## @file
# Retrieves the people to request review from on submission of a commit. # Retrieves the people to request review from on submission of a commit.
# #
# Copyright (c) 2019, Linaro Ltd. All rights reserved.<BR> # Copyright (c) 2019, Linaro Ltd. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
from __future__ import print_function from __future__ import print_function
from collections import defaultdict from collections import defaultdict
from collections import OrderedDict from collections import OrderedDict
import argparse import argparse
import os import os
import re import re
import SetupGit import SetupGit
EXPRESSIONS = { EXPRESSIONS = {
'exclude': re.compile(r'^X:\s*(?P<exclude>.*?)\r*$'), 'exclude': re.compile(r'^X:\s*(?P<exclude>.*?)\r*$'),
'file': re.compile(r'^F:\s*(?P<file>.*?)\r*$'), 'file': re.compile(r'^F:\s*(?P<file>.*?)\r*$'),
'list': re.compile(r'^L:\s*(?P<list>.*?)\r*$'), 'list': re.compile(r'^L:\s*(?P<list>.*?)\r*$'),
'maintainer': re.compile(r'^M:\s*(?P<maintainer>.*<.*?>)\r*$'), 'maintainer': re.compile(r'^M:\s*(?P<maintainer>.*<.*?>)\r*$'),
'reviewer': re.compile(r'^R:\s*(?P<reviewer>.*?)\r*$'), 'reviewer': re.compile(r'^R:\s*(?P<reviewer>.*?)\r*$'),
'status': re.compile(r'^S:\s*(?P<status>.*?)\r*$'), 'status': re.compile(r'^S:\s*(?P<status>.*?)\r*$'),
'tree': re.compile(r'^T:\s*(?P<tree>.*?)\r*$'), 'tree': re.compile(r'^T:\s*(?P<tree>.*?)\r*$'),
'webpage': re.compile(r'^W:\s*(?P<webpage>.*?)\r*$') 'webpage': re.compile(r'^W:\s*(?P<webpage>.*?)\r*$')
} }
def printsection(section): def printsection(section):
"""Prints out the dictionary describing a Maintainers.txt section.""" """Prints out the dictionary describing a Maintainers.txt section."""
print('===') print('===')
for key in section.keys(): for key in section.keys():
print("Key: %s" % key) print("Key: %s" % key)
for item in section[key]: for item in section[key]:
print(' %s' % item) print(' %s' % item)
def pattern_to_regex(pattern): def pattern_to_regex(pattern):
"""Takes a string containing regular UNIX path wildcards """Takes a string containing regular UNIX path wildcards
and returns a string suitable for matching with regex.""" and returns a string suitable for matching with regex."""
pattern = pattern.replace('.', r'\.') pattern = pattern.replace('.', r'\.')
pattern = pattern.replace('?', r'.') pattern = pattern.replace('?', r'.')
pattern = pattern.replace('*', r'.*') pattern = pattern.replace('*', r'.*')
if pattern.endswith('/'): if pattern.endswith('/'):
pattern += r'.*' pattern += r'.*'
elif pattern.endswith('.*'): elif pattern.endswith('.*'):
pattern = pattern[:-2] pattern = pattern[:-2]
pattern += r'(?!.*?/.*?)' pattern += r'(?!.*?/.*?)'
return pattern return pattern
def path_in_section(path, section): def path_in_section(path, section):
"""Returns True of False indicating whether the path is covered by """Returns True of False indicating whether the path is covered by
the current section.""" the current section."""
if not 'file' in section: if not 'file' in section:
return False return False
for pattern in section['file']: for pattern in section['file']:
regex = pattern_to_regex(pattern) regex = pattern_to_regex(pattern)
match = re.match(regex, path) match = re.match(regex, path)
if match: if match:
# Check if there is an exclude pattern that applies # Check if there is an exclude pattern that applies
for pattern in section['exclude']: for pattern in section['exclude']:
regex = pattern_to_regex(pattern) regex = pattern_to_regex(pattern)
match = re.match(regex, path) match = re.match(regex, path)
if match: if match:
return False return False
return True return True
return False return False
def get_section_maintainers(path, section): def get_section_maintainers(path, section):
"""Returns a list with email addresses to any M: and R: entries """Returns a list with email addresses to any M: and R: entries
matching the provided path in the provided section.""" matching the provided path in the provided section."""
maintainers = [] maintainers = []
lists = [] lists = []
nowarn_status = ['Supported', 'Maintained'] nowarn_status = ['Supported', 'Maintained']
if path_in_section(path, section): if path_in_section(path, section):
for status in section['status']: for status in section['status']:
if status not in nowarn_status: if status not in nowarn_status:
print('WARNING: Maintained status for "%s" is \'%s\'!' % (path, status)) print('WARNING: Maintained status for "%s" is \'%s\'!' % (path, status))
for address in section['maintainer'], section['reviewer']: for address in section['maintainer'], section['reviewer']:
# Convert to list if necessary # Convert to list if necessary
if isinstance(address, list): if isinstance(address, list):
maintainers += address maintainers += address
else: else:
lists += [address] lists += [address]
for address in section['list']: for address in section['list']:
# Convert to list if necessary # Convert to list if necessary
if isinstance(address, list): if isinstance(address, list):
lists += address lists += address
else: else:
lists += [address] lists += [address]
return maintainers, lists return maintainers, lists
def get_maintainers(path, sections, level=0): def get_maintainers(path, sections, level=0):
"""For 'path', iterates over all sections, returning maintainers """For 'path', iterates over all sections, returning maintainers
for matching ones.""" for matching ones."""
maintainers = [] maintainers = []
lists = [] lists = []
for section in sections: for section in sections:
tmp_maint, tmp_lists = get_section_maintainers(path, section) tmp_maint, tmp_lists = get_section_maintainers(path, section)
if tmp_maint: if tmp_maint:
maintainers += tmp_maint maintainers += tmp_maint
if tmp_lists: if tmp_lists:
lists += tmp_lists lists += tmp_lists
if not maintainers: if not maintainers:
# If no match found, look for match for (nonexistent) file # If no match found, look for match for (nonexistent) file
# REPO.working_dir/<default> # REPO.working_dir/<default>
print('"%s": no maintainers found, looking for default' % path) print('"%s": no maintainers found, looking for default' % path)
if level == 0: if level == 0:
maintainers = get_maintainers('<default>', sections, level=level + 1) maintainers = get_maintainers('<default>', sections, level=level + 1)
else: else:
print("No <default> maintainers set for project.") print("No <default> maintainers set for project.")
if not maintainers: if not maintainers:
return None return None
return maintainers + lists return maintainers + lists
def parse_maintainers_line(line): def parse_maintainers_line(line):
"""Parse one line of Maintainers.txt, returning any match group and its key.""" """Parse one line of Maintainers.txt, returning any match group and its key."""
for key, expression in EXPRESSIONS.items(): for key, expression in EXPRESSIONS.items():
match = expression.match(line) match = expression.match(line)
if match: if match:
return key, match.group(key) return key, match.group(key)
return None, None return None, None
def parse_maintainers_file(filename): def parse_maintainers_file(filename):
"""Parse the Maintainers.txt from top-level of repo and """Parse the Maintainers.txt from top-level of repo and
return a list containing dictionaries of all sections.""" return a list containing dictionaries of all sections."""
with open(filename, 'r') as text: with open(filename, 'r') as text:
line = text.readline() line = text.readline()
sectionlist = [] sectionlist = []
section = defaultdict(list) section = defaultdict(list)
while line: while line:
key, value = parse_maintainers_line(line) key, value = parse_maintainers_line(line)
if key and value: if key and value:
section[key].append(value) section[key].append(value)
line = text.readline() line = text.readline()
# If end of section (end of file, or non-tag line encountered)... # If end of section (end of file, or non-tag line encountered)...
if not key or not value or not line: if not key or not value or not line:
# ...if non-empty, append section to list. # ...if non-empty, append section to list.
if section: if section:
sectionlist.append(section.copy()) sectionlist.append(section.copy())
section.clear() section.clear()
return sectionlist return sectionlist
def get_modified_files(repo, args): def get_modified_files(repo, args):
"""Returns a list of the files modified by the commit specified in 'args'.""" """Returns a list of the files modified by the commit specified in 'args'."""
commit = repo.commit(args.commit) commit = repo.commit(args.commit)
return commit.stats.files return commit.stats.files
if __name__ == '__main__': if __name__ == '__main__':
PARSER = argparse.ArgumentParser( PARSER = argparse.ArgumentParser(
description='Retrieves information on who to cc for review on a given commit') description='Retrieves information on who to cc for review on a given commit')
PARSER.add_argument('commit', PARSER.add_argument('commit',
action="store", action="store",
help='git revision to examine (default: HEAD)', help='git revision to examine (default: HEAD)',
nargs='?', nargs='?',
default='HEAD') default='HEAD')
PARSER.add_argument('-l', '--lookup', PARSER.add_argument('-l', '--lookup',
help='Find section matches for path LOOKUP', help='Find section matches for path LOOKUP',
required=False) required=False)
ARGS = PARSER.parse_args() ARGS = PARSER.parse_args()
REPO = SetupGit.locate_repo() REPO = SetupGit.locate_repo()
CONFIG_FILE = os.path.join(REPO.working_dir, 'Maintainers.txt') CONFIG_FILE = os.path.join(REPO.working_dir, 'Maintainers.txt')
SECTIONS = parse_maintainers_file(CONFIG_FILE) SECTIONS = parse_maintainers_file(CONFIG_FILE)
if ARGS.lookup: if ARGS.lookup:
FILES = [ARGS.lookup] FILES = [ARGS.lookup]
else: else:
FILES = get_modified_files(REPO, ARGS) FILES = get_modified_files(REPO, ARGS)
ADDRESSES = [] ADDRESSES = []
for file in FILES: for file in FILES:
print(file) print(file)
addresslist = get_maintainers(file, SECTIONS) addresslist = get_maintainers(file, SECTIONS)
if addresslist: if addresslist:
ADDRESSES += addresslist ADDRESSES += addresslist
for address in list(OrderedDict.fromkeys(ADDRESSES)): for address in list(OrderedDict.fromkeys(ADDRESSES)):
print(' %s' % address) print(' %s' % address)