mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
.pytool/Plugin/UncrustifyCheck: Run Black formatter
Runs the Black formatter against UncrustifyCheck.py so is formatted to PEP-8. No functional changes are made. https://pypi.org/project/black/ Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
This commit is contained in:
parent
4074b5db5d
commit
e0d2cb29fe
1 changed files with 258 additions and 114 deletions
|
|
@ -22,10 +22,11 @@ from edk2toolext.environment.var_dict import VarDict
|
|||
from edk2toollib.gitignore_parser import parse_gitignore_lines
|
||||
from edk2toollib.log.junit_report_format import JunitReportTestCase
|
||||
from edk2toollib.uefi.edk2.path_utilities import Edk2Path
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
from edk2toollib.utility_functions import RunCmd
|
||||
from io import StringIO
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
|
||||
#
|
||||
# Provide more user friendly messages for certain scenarios
|
||||
#
|
||||
|
|
@ -59,6 +60,7 @@ class UncrustifyInputFileCreationErrorException(UncrustifyException):
|
|||
def __init__(self, message):
|
||||
super().__init__(message, -121)
|
||||
|
||||
|
||||
class UncrustifyInvalidIgnoreStandardPathsException(UncrustifyException):
|
||||
def __init__(self, message):
|
||||
super().__init__(message, -122)
|
||||
|
|
@ -91,7 +93,8 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
# Note: Values specified via "ConfigFilePath" are relative to the package
|
||||
#
|
||||
DEFAULT_CONFIG_FILE_PATH = os.path.join(
|
||||
pathlib.Path(__file__).parent.resolve(), "uncrustify.cfg")
|
||||
pathlib.Path(__file__).parent.resolve(), "uncrustify.cfg"
|
||||
)
|
||||
|
||||
#
|
||||
# The extension used for formatted files produced by this plugin
|
||||
|
|
@ -110,20 +113,33 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
UNCRUSTIFY_PATH_ENV_KEY = "UNCRUSTIFY_CI_PATH"
|
||||
|
||||
def GetTestName(self, packagename: str, environment: VarDict) -> Tuple:
|
||||
""" Provide the testcase name and classname for use in reporting
|
||||
"""Provide the testcase name and classname for use in reporting
|
||||
|
||||
Args:
|
||||
packagename: string containing name of package to build
|
||||
environment: The VarDict for the test to run in
|
||||
Returns:
|
||||
A tuple containing the testcase name and the classname
|
||||
(testcasename, classname)
|
||||
testclassname: a descriptive string for the testcase can include whitespace
|
||||
classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
|
||||
Args:
|
||||
packagename: string containing name of package to build
|
||||
environment: The VarDict for the test to run in
|
||||
Returns:
|
||||
A tuple containing the testcase name and the classname
|
||||
(testcasename, classname)
|
||||
testclassname: a descriptive string for the testcase can include whitespace
|
||||
classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
|
||||
"""
|
||||
return ("Check file coding standard compliance in " + packagename, packagename + ".UncrustifyCheck")
|
||||
return (
|
||||
"Check file coding standard compliance in " + packagename,
|
||||
packagename + ".UncrustifyCheck",
|
||||
)
|
||||
|
||||
def RunBuildPlugin(self, package_rel_path: str, edk2_path: Edk2Path, package_config: Dict[str, List[str]], environment_config: Any, plugin_manager: PluginManager, plugin_manager_helper: HelperFunctions, tc: JunitReportTestCase, output_stream=None) -> int:
|
||||
def RunBuildPlugin(
|
||||
self,
|
||||
package_rel_path: str,
|
||||
edk2_path: Edk2Path,
|
||||
package_config: Dict[str, List[str]],
|
||||
environment_config: Any,
|
||||
plugin_manager: PluginManager,
|
||||
plugin_manager_helper: HelperFunctions,
|
||||
tc: JunitReportTestCase,
|
||||
output_stream=None,
|
||||
) -> int:
|
||||
"""
|
||||
External function of plugin. This function is used to perform the task of the CiBuild Plugin.
|
||||
|
||||
|
|
@ -146,7 +162,8 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
# Initialize plugin and check pre-requisites.
|
||||
self._env = environment_config
|
||||
self._initialize_environment_info(
|
||||
package_rel_path, edk2_path, package_config, tc)
|
||||
package_rel_path, edk2_path, package_config, tc
|
||||
)
|
||||
self._initialize_configuration()
|
||||
self._check_for_preexisting_formatted_files()
|
||||
|
||||
|
|
@ -167,20 +184,21 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
|
||||
except UncrustifyException as e:
|
||||
self._tc.LogStdError(
|
||||
f"Uncrustify error {e.exit_code}. Details:\n\n{str(e)}")
|
||||
logging.warning(
|
||||
f"Uncrustify error {e.exit_code}. Details:\n\n{str(e)}")
|
||||
f"Uncrustify error {e.exit_code}. Details:\n\n{str(e)}"
|
||||
)
|
||||
logging.warning(f"Uncrustify error {e.exit_code}. Details:\n\n{str(e)}")
|
||||
return -1
|
||||
else:
|
||||
if self._formatted_file_error_count > 0:
|
||||
if self._audit_only_mode:
|
||||
logging.info(
|
||||
"Setting test as skipped since AuditOnly is enabled")
|
||||
logging.info("Setting test as skipped since AuditOnly is enabled")
|
||||
self._tc.SetSkipped()
|
||||
return -1
|
||||
else:
|
||||
self._tc.SetFailed(
|
||||
f"{self._plugin_name} failed due to {self._formatted_file_error_count} incorrectly formatted files.", "CHECK_FAILED")
|
||||
f"{self._plugin_name} failed due to {self._formatted_file_error_count} incorrectly formatted files.",
|
||||
"CHECK_FAILED",
|
||||
)
|
||||
else:
|
||||
self._tc.SetSuccess()
|
||||
return self._formatted_file_error_count
|
||||
|
|
@ -205,11 +223,18 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
from an error that occurred during a previous run or a premature exit from a debug scenario. In any case, the package should be clean before starting a new run.
|
||||
"""
|
||||
pre_existing_formatted_file_count = len(
|
||||
[str(path.resolve()) for path in pathlib.Path(self._abs_package_path).rglob(f'*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}')])
|
||||
[
|
||||
str(path.resolve())
|
||||
for path in pathlib.Path(self._abs_package_path).rglob(
|
||||
f"*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}"
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
if pre_existing_formatted_file_count > 0:
|
||||
raise UncrustifyStalePluginFormattedFilesException(
|
||||
f"{pre_existing_formatted_file_count} formatted files already exist. To prevent overwriting these files, please remove them before running this plugin.")
|
||||
f"{pre_existing_formatted_file_count} formatted files already exist. To prevent overwriting these files, please remove them before running this plugin."
|
||||
)
|
||||
|
||||
def _cleanup_temporary_directory(self) -> None:
|
||||
"""
|
||||
|
|
@ -217,7 +242,7 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
|
||||
This removes the directory and all files created during this instance.
|
||||
"""
|
||||
if hasattr(self, '_working_dir'):
|
||||
if hasattr(self, "_working_dir"):
|
||||
self._remove_tree(self._working_dir)
|
||||
|
||||
def _cleanup_temporary_formatted_files(self) -> None:
|
||||
|
|
@ -227,9 +252,13 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
This will recursively remove all formatted files generated by Uncrustify
|
||||
during this execution instance.
|
||||
"""
|
||||
if hasattr(self, '_abs_package_path'):
|
||||
formatted_files = [str(path.resolve()) for path in pathlib.Path(
|
||||
self._abs_package_path).rglob(f'*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}')]
|
||||
if hasattr(self, "_abs_package_path"):
|
||||
formatted_files = [
|
||||
str(path.resolve())
|
||||
for path in pathlib.Path(self._abs_package_path).rglob(
|
||||
f"*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}"
|
||||
)
|
||||
]
|
||||
|
||||
for formatted_file in formatted_files:
|
||||
os.remove(formatted_file)
|
||||
|
|
@ -239,22 +268,29 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
Creates the temporary directory used for this execution instance.
|
||||
"""
|
||||
self._working_dir = os.path.join(
|
||||
self._abs_workspace_path, "Build", ".pytool", "Plugin", f"{self._plugin_name}")
|
||||
self._abs_workspace_path,
|
||||
"Build",
|
||||
".pytool",
|
||||
"Plugin",
|
||||
f"{self._plugin_name}",
|
||||
)
|
||||
|
||||
try:
|
||||
pathlib.Path(self._working_dir).mkdir(parents=True, exist_ok=True)
|
||||
except OSError as e:
|
||||
raise UncrustifyInputFileCreationErrorException(
|
||||
f"Error creating plugin directory {self._working_dir}.\n\n{repr(e)}.")
|
||||
f"Error creating plugin directory {self._working_dir}.\n\n{repr(e)}."
|
||||
)
|
||||
|
||||
def _create_uncrustify_file_list_file(self) -> None:
|
||||
"""
|
||||
Creates the file with the list of source files for Uncrustify to process.
|
||||
"""
|
||||
self._app_input_file_path = os.path.join(
|
||||
self._working_dir, "uncrustify_file_list.txt")
|
||||
self._working_dir, "uncrustify_file_list.txt"
|
||||
)
|
||||
|
||||
with open(self._app_input_file_path, 'w', encoding='utf8') as f:
|
||||
with open(self._app_input_file_path, "w", encoding="utf8") as f:
|
||||
f.writelines(f"\n".join(self._abs_file_paths_to_format))
|
||||
|
||||
def _execute_uncrustify(self) -> None:
|
||||
|
|
@ -262,21 +298,18 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
Executes Uncrustify with the initialized configuration.
|
||||
"""
|
||||
output = StringIO()
|
||||
params = ['-c', self._app_config_file]
|
||||
params += ['-F', self._app_input_file_path]
|
||||
params += ['--if-changed']
|
||||
params = ["-c", self._app_config_file]
|
||||
params += ["-F", self._app_input_file_path]
|
||||
params += ["--if-changed"]
|
||||
if self._env.GetValue("UNCRUSTIFY_IN_PLACE", "FALSE") == "TRUE":
|
||||
params += ['--replace', '--no-backup']
|
||||
params += ["--replace", "--no-backup"]
|
||||
else:
|
||||
params += ['--suffix', UncrustifyCheck.FORMATTED_FILE_EXTENSION]
|
||||
self._app_exit_code = RunCmd(
|
||||
self._app_path,
|
||||
" ".join(params),
|
||||
outstream=output)
|
||||
params += ["--suffix", UncrustifyCheck.FORMATTED_FILE_EXTENSION]
|
||||
self._app_exit_code = RunCmd(self._app_path, " ".join(params), outstream=output)
|
||||
self._app_output = output.getvalue().strip().splitlines()
|
||||
|
||||
def _get_files_ignored_in_config(self):
|
||||
""""
|
||||
""" "
|
||||
Returns a function that returns true if a given file string path is ignored in the plugin configuration file and false otherwise.
|
||||
"""
|
||||
ignored_files = []
|
||||
|
|
@ -291,7 +324,9 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
# This information is only used for reporting (not used here) and
|
||||
# the ignore lines are being passed directly as they are given to
|
||||
# this plugin.
|
||||
return parse_gitignore_lines(ignored_files, "Package configuration file", self._abs_package_path)
|
||||
return parse_gitignore_lines(
|
||||
ignored_files, "Package configuration file", self._abs_package_path
|
||||
)
|
||||
|
||||
def _get_git_ignored_paths(self) -> List[str]:
|
||||
"""
|
||||
|
|
@ -304,11 +339,17 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
return []
|
||||
|
||||
outstream_buffer = StringIO()
|
||||
exit_code = RunCmd("git", "ls-files --other",
|
||||
workingdir=self._abs_git_repo_path, outstream=outstream_buffer, logging_level=logging.NOTSET)
|
||||
exit_code = RunCmd(
|
||||
"git",
|
||||
"ls-files --other",
|
||||
workingdir=self._abs_git_repo_path,
|
||||
outstream=outstream_buffer,
|
||||
logging_level=logging.NOTSET,
|
||||
)
|
||||
if exit_code != 0:
|
||||
logging.warning(
|
||||
"An error occurred reading git ignore settings. Git ignored paths will not be considered.")
|
||||
"An error occurred reading git ignore settings. Git ignored paths will not be considered."
|
||||
)
|
||||
return []
|
||||
|
||||
# Note: This will potentially be a large list, but at least sorted
|
||||
|
|
@ -316,7 +357,8 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
abs_paths = []
|
||||
for path in rel_paths:
|
||||
abs_paths.append(
|
||||
os.path.normpath(os.path.join(self._abs_git_repo_path, path)))
|
||||
os.path.normpath(os.path.join(self._abs_git_repo_path, path))
|
||||
)
|
||||
return abs_paths
|
||||
|
||||
def _get_git_repo_path(self) -> Optional[str]:
|
||||
|
|
@ -330,15 +372,22 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
"""
|
||||
if not shutil.which("git"):
|
||||
logging.warning(
|
||||
"Git is not found on this system. Git exclusions will not be considered.")
|
||||
"Git is not found on this system. Git exclusions will not be considered."
|
||||
)
|
||||
return None
|
||||
|
||||
outstream_buffer = StringIO()
|
||||
exit_code = RunCmd("git", "rev-parse --show-toplevel",
|
||||
workingdir=self._abs_package_path, outstream=outstream_buffer, logging_level=logging.NOTSET)
|
||||
exit_code = RunCmd(
|
||||
"git",
|
||||
"rev-parse --show-toplevel",
|
||||
workingdir=self._abs_package_path,
|
||||
outstream=outstream_buffer,
|
||||
logging_level=logging.NOTSET,
|
||||
)
|
||||
if exit_code != 0:
|
||||
logging.warning(
|
||||
f"{self._package_name} does not appear to be in a git workspace. Git exclusions will not be considered.")
|
||||
f"{self._package_name} does not appear to be in a git workspace. Git exclusions will not be considered."
|
||||
)
|
||||
return None
|
||||
|
||||
return os.path.normpath(outstream_buffer.getvalue().strip())
|
||||
|
|
@ -356,19 +405,30 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
|
||||
if os.path.isfile(os.path.join(self._abs_git_repo_path, ".gitmodules")):
|
||||
logging.info(
|
||||
f".gitmodules file found. Excluding submodules in {self._package_name}.")
|
||||
f".gitmodules file found. Excluding submodules in {self._package_name}."
|
||||
)
|
||||
|
||||
outstream_buffer = StringIO()
|
||||
exit_code = RunCmd("git", "config --file .gitmodules --get-regexp path", workingdir=self._abs_git_repo_path, outstream=outstream_buffer, logging_level=logging.NOTSET)
|
||||
exit_code = RunCmd(
|
||||
"git",
|
||||
"config --file .gitmodules --get-regexp path",
|
||||
workingdir=self._abs_git_repo_path,
|
||||
outstream=outstream_buffer,
|
||||
logging_level=logging.NOTSET,
|
||||
)
|
||||
if exit_code != 0:
|
||||
logging.warning(
|
||||
".gitmodules file detected but an error occurred reading it. Git submodule paths will not be considered.")
|
||||
".gitmodules file detected but an error occurred reading it. Git submodule paths will not be considered."
|
||||
)
|
||||
return []
|
||||
|
||||
submodule_paths = []
|
||||
for line in outstream_buffer.getvalue().strip().splitlines():
|
||||
submodule_paths.append(
|
||||
os.path.normpath(os.path.join(self._abs_git_repo_path, line.split()[1])))
|
||||
os.path.normpath(
|
||||
os.path.join(self._abs_git_repo_path, line.split()[1])
|
||||
)
|
||||
)
|
||||
|
||||
return submodule_paths
|
||||
else:
|
||||
|
|
@ -386,7 +446,7 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
# Allow no value to allow "set" statements in the config file which do
|
||||
# not specify value assignment
|
||||
parser = configparser.ConfigParser(allow_no_value=True)
|
||||
with open(self._app_config_file, 'r') as cf:
|
||||
with open(self._app_config_file, "r") as cf:
|
||||
parser.read_string("[dummy_section]\n" + cf.read())
|
||||
|
||||
try:
|
||||
|
|
@ -395,7 +455,9 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
file_template_path = pathlib.Path(file_template_name)
|
||||
|
||||
if not file_template_path.is_file():
|
||||
file_template_path = pathlib.Path(os.path.join(self._plugin_path, file_template_name))
|
||||
file_template_path = pathlib.Path(
|
||||
os.path.join(self._plugin_path, file_template_name)
|
||||
)
|
||||
self._file_template_contents = file_template_path.read_text()
|
||||
except KeyError:
|
||||
logging.info("A file header template is not specified in the config file.")
|
||||
|
|
@ -407,10 +469,14 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
func_template_path = pathlib.Path(func_template_name)
|
||||
|
||||
if not func_template_path.is_file():
|
||||
func_template_path = pathlib.Path(os.path.join(self._plugin_path, func_template_name))
|
||||
func_template_path = pathlib.Path(
|
||||
os.path.join(self._plugin_path, func_template_name)
|
||||
)
|
||||
self._func_template_contents = func_template_path.read_text()
|
||||
except KeyError:
|
||||
logging.info("A function header template is not specified in the config file.")
|
||||
logging.info(
|
||||
"A function header template is not specified in the config file."
|
||||
)
|
||||
except FileNotFoundError:
|
||||
logging.info("The specified function header template file was not found.")
|
||||
|
||||
|
|
@ -423,32 +489,39 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
# Verify Uncrustify is specified in the environment.
|
||||
if UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY not in os.environ:
|
||||
raise UncrustifyAppEnvVarNotFoundException(
|
||||
f"Uncrustify environment variable {UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY} is not present.")
|
||||
f"Uncrustify environment variable {UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY} is not present."
|
||||
)
|
||||
|
||||
self._app_path = shutil.which('uncrustify', path=os.environ[UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY])
|
||||
self._app_path = shutil.which(
|
||||
"uncrustify", path=os.environ[UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY]
|
||||
)
|
||||
|
||||
if self._app_path is None:
|
||||
raise FileNotFoundError(
|
||||
errno.ENOENT, os.strerror(errno.ENOENT), self._app_path)
|
||||
errno.ENOENT, os.strerror(errno.ENOENT), self._app_path
|
||||
)
|
||||
|
||||
self._app_path = os.path.normcase(os.path.normpath(self._app_path))
|
||||
|
||||
if not os.path.isfile(self._app_path):
|
||||
raise FileNotFoundError(
|
||||
errno.ENOENT, os.strerror(errno.ENOENT), self._app_path)
|
||||
errno.ENOENT, os.strerror(errno.ENOENT), self._app_path
|
||||
)
|
||||
|
||||
# Verify Uncrustify is present at the expected path.
|
||||
return_buffer = StringIO()
|
||||
ret = RunCmd(self._app_path, "--version", outstream=return_buffer)
|
||||
if (ret != 0):
|
||||
if ret != 0:
|
||||
raise UncrustifyAppVersionErrorException(
|
||||
f"Error occurred executing --version: {ret}.")
|
||||
f"Error occurred executing --version: {ret}."
|
||||
)
|
||||
|
||||
# Log Uncrustify version information.
|
||||
self._app_version = return_buffer.getvalue().strip()
|
||||
self._tc.LogStdOut(f"Uncrustify version: {self._app_version}")
|
||||
version_aggregator.GetVersionAggregator().ReportVersion(
|
||||
"Uncrustify", self._app_version, version_aggregator.VersionTypes.INFO)
|
||||
"Uncrustify", self._app_version, version_aggregator.VersionTypes.INFO
|
||||
)
|
||||
|
||||
def _initialize_config_file_info(self) -> None:
|
||||
"""
|
||||
|
|
@ -461,22 +534,30 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
self._app_config_file = self._package_config["ConfigFilePath"].strip()
|
||||
|
||||
self._app_config_file = os.path.normpath(
|
||||
os.path.join(self._abs_package_path, self._app_config_file))
|
||||
os.path.join(self._abs_package_path, self._app_config_file)
|
||||
)
|
||||
|
||||
if not os.path.isfile(self._app_config_file):
|
||||
raise FileNotFoundError(
|
||||
errno.ENOENT, os.strerror(errno.ENOENT), self._app_config_file)
|
||||
errno.ENOENT, os.strerror(errno.ENOENT), self._app_config_file
|
||||
)
|
||||
|
||||
def _initialize_environment_info(self, package_rel_path: str, edk2_path: Edk2Path, package_config: Dict[str, List[str]], tc: JunitReportTestCase) -> None:
|
||||
def _initialize_environment_info(
|
||||
self,
|
||||
package_rel_path: str,
|
||||
edk2_path: Edk2Path,
|
||||
package_config: Dict[str, List[str]],
|
||||
tc: JunitReportTestCase,
|
||||
) -> None:
|
||||
"""
|
||||
Initializes plugin environment information.
|
||||
"""
|
||||
self._abs_package_path = edk2_path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(
|
||||
package_rel_path)
|
||||
self._abs_package_path = (
|
||||
edk2_path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(package_rel_path)
|
||||
)
|
||||
self._abs_workspace_path = edk2_path.WorkspacePath
|
||||
self._package_config = package_config
|
||||
self._package_name = os.path.basename(
|
||||
os.path.normpath(package_rel_path))
|
||||
self._package_name = os.path.basename(os.path.normpath(package_rel_path))
|
||||
self._plugin_name = self.__class__.__name__
|
||||
self._plugin_path = os.path.dirname(os.path.realpath(__file__))
|
||||
self._rel_package_path = package_rel_path
|
||||
|
|
@ -487,71 +568,93 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
Forms the list of source files for Uncrustify to process.
|
||||
"""
|
||||
# Create a list of all the package relative file paths in the package to run against Uncrustify.
|
||||
rel_file_paths_to_format = list(
|
||||
UncrustifyCheck.STANDARD_PLUGIN_DEFINED_PATHS)
|
||||
rel_file_paths_to_format = list(UncrustifyCheck.STANDARD_PLUGIN_DEFINED_PATHS)
|
||||
|
||||
# Allow the ci.yaml to remove any of the pre-defined standard paths
|
||||
if "IgnoreStandardPaths" in self._package_config:
|
||||
for a in self._package_config["IgnoreStandardPaths"]:
|
||||
if a.strip() in rel_file_paths_to_format:
|
||||
self._tc.LogStdOut(
|
||||
f"Ignoring standard path due to ci.yaml ignore: {a}")
|
||||
f"Ignoring standard path due to ci.yaml ignore: {a}"
|
||||
)
|
||||
rel_file_paths_to_format.remove(a.strip())
|
||||
else:
|
||||
raise UncrustifyInvalidIgnoreStandardPathsException(f"Invalid IgnoreStandardPaths value: {a}")
|
||||
raise UncrustifyInvalidIgnoreStandardPathsException(
|
||||
f"Invalid IgnoreStandardPaths value: {a}"
|
||||
)
|
||||
|
||||
# Allow the ci.yaml to specify additional include paths for this package
|
||||
if "AdditionalIncludePaths" in self._package_config:
|
||||
rel_file_paths_to_format.extend(
|
||||
self._package_config["AdditionalIncludePaths"])
|
||||
self._package_config["AdditionalIncludePaths"]
|
||||
)
|
||||
|
||||
self._abs_file_paths_to_format = []
|
||||
for path in rel_file_paths_to_format:
|
||||
self._abs_file_paths_to_format.extend(
|
||||
[str(path.resolve()) for path in pathlib.Path(self._abs_package_path).rglob(path)])
|
||||
[
|
||||
str(path.resolve())
|
||||
for path in pathlib.Path(self._abs_package_path).rglob(path)
|
||||
]
|
||||
)
|
||||
|
||||
# Remove files ignore in the plugin configuration file
|
||||
plugin_ignored_files = list(filter(self._get_files_ignored_in_config(), self._abs_file_paths_to_format))
|
||||
plugin_ignored_files = list(
|
||||
filter(self._get_files_ignored_in_config(), self._abs_file_paths_to_format)
|
||||
)
|
||||
|
||||
if plugin_ignored_files:
|
||||
logging.info(
|
||||
f"{self._package_name} file count before plugin ignore file exclusion: {len(self._abs_file_paths_to_format)}")
|
||||
f"{self._package_name} file count before plugin ignore file exclusion: {len(self._abs_file_paths_to_format)}"
|
||||
)
|
||||
for path in plugin_ignored_files:
|
||||
if path in self._abs_file_paths_to_format:
|
||||
logging.info(f" File ignored in plugin config file: {path}")
|
||||
self._abs_file_paths_to_format.remove(path)
|
||||
logging.info(
|
||||
f"{self._package_name} file count after plugin ignore file exclusion: {len(self._abs_file_paths_to_format)}")
|
||||
f"{self._package_name} file count after plugin ignore file exclusion: {len(self._abs_file_paths_to_format)}"
|
||||
)
|
||||
|
||||
if not "SkipGitExclusions" in self._package_config or not self._package_config["SkipGitExclusions"]:
|
||||
if (
|
||||
not "SkipGitExclusions" in self._package_config
|
||||
or not self._package_config["SkipGitExclusions"]
|
||||
):
|
||||
# Determine the git repository that contains this package. This is not necessarily
|
||||
# the edk2 repository if the package is in a different repo (e.g. PACKAGES_PATH).
|
||||
self._abs_git_repo_path = self._get_git_repo_path()
|
||||
|
||||
# Remove files ignored by git
|
||||
logging.info(
|
||||
f"{self._package_name} file count before git ignore file exclusion: {len(self._abs_file_paths_to_format)}")
|
||||
f"{self._package_name} file count before git ignore file exclusion: {len(self._abs_file_paths_to_format)}"
|
||||
)
|
||||
|
||||
ignored_paths = self._get_git_ignored_paths()
|
||||
self._abs_file_paths_to_format = list(
|
||||
set(self._abs_file_paths_to_format).difference(ignored_paths))
|
||||
set(self._abs_file_paths_to_format).difference(ignored_paths)
|
||||
)
|
||||
|
||||
logging.info(
|
||||
f"{self._package_name} file count after git ignore file exclusion: {len(self._abs_file_paths_to_format)}")
|
||||
f"{self._package_name} file count after git ignore file exclusion: {len(self._abs_file_paths_to_format)}"
|
||||
)
|
||||
|
||||
# Remove files in submodules
|
||||
logging.info(
|
||||
f"{self._package_name} file count before submodule exclusion: {len(self._abs_file_paths_to_format)}")
|
||||
f"{self._package_name} file count before submodule exclusion: {len(self._abs_file_paths_to_format)}"
|
||||
)
|
||||
|
||||
submodule_paths = tuple(self._get_git_submodule_paths())
|
||||
for path in submodule_paths:
|
||||
logging.info(f" submodule path: {path}")
|
||||
|
||||
self._abs_file_paths_to_format = [
|
||||
f for f in self._abs_file_paths_to_format if not f.startswith(submodule_paths)]
|
||||
f
|
||||
for f in self._abs_file_paths_to_format
|
||||
if not f.startswith(submodule_paths)
|
||||
]
|
||||
|
||||
logging.info(
|
||||
f"{self._package_name} file count after submodule exclusion: {len(self._abs_file_paths_to_format)}")
|
||||
f"{self._package_name} file count after submodule exclusion: {len(self._abs_file_paths_to_format)}"
|
||||
)
|
||||
|
||||
# Sort the files for more consistent results
|
||||
self._abs_file_paths_to_format.sort()
|
||||
|
|
@ -566,7 +669,10 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
if "AuditOnly" in self._package_config and self._package_config["AuditOnly"]:
|
||||
self._audit_only_mode = True
|
||||
|
||||
if "OutputFileDiffs" in self._package_config and not self._package_config["OutputFileDiffs"]:
|
||||
if (
|
||||
"OutputFileDiffs" in self._package_config
|
||||
and not self._package_config["OutputFileDiffs"]
|
||||
):
|
||||
self._output_file_diffs = False
|
||||
|
||||
def _log_uncrustify_app_info(self) -> None:
|
||||
|
|
@ -575,10 +681,10 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
"""
|
||||
self._tc.LogStdOut(f"Found Uncrustify at {self._app_path}")
|
||||
self._tc.LogStdOut(f"Uncrustify version: {self._app_version}")
|
||||
self._tc.LogStdOut('\n')
|
||||
self._tc.LogStdOut("\n")
|
||||
logging.info(f"Found Uncrustify at {self._app_path}")
|
||||
logging.info(f"Uncrustify version: {self._app_version}")
|
||||
logging.info('\n')
|
||||
logging.info("\n")
|
||||
|
||||
def _process_uncrustify_results(self) -> None:
|
||||
"""
|
||||
|
|
@ -586,55 +692,90 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
|
||||
Determines whether formatting errors are present and logs failures.
|
||||
"""
|
||||
formatted_files = [str(path.resolve()) for path in pathlib.Path(
|
||||
self._abs_package_path).rglob(f'*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}')]
|
||||
formatted_files = [
|
||||
str(path.resolve())
|
||||
for path in pathlib.Path(self._abs_package_path).rglob(
|
||||
f"*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}"
|
||||
)
|
||||
]
|
||||
|
||||
self._formatted_file_error_count = len(formatted_files)
|
||||
|
||||
if self._formatted_file_error_count > 0:
|
||||
logging.error(f'Uncrustify found {self._formatted_file_error_count} files with formatting errors\n')
|
||||
self._tc.LogStdError(f"Uncrustify found {self._formatted_file_error_count} files with formatting errors:\n")
|
||||
logging.error(
|
||||
f"Uncrustify found {self._formatted_file_error_count} files with formatting errors\n"
|
||||
)
|
||||
self._tc.LogStdError(
|
||||
f"Uncrustify found {self._formatted_file_error_count} files with formatting errors:\n"
|
||||
)
|
||||
logging.warning(
|
||||
"Visit the following instructions to learn "
|
||||
"more about uncrustify setup instructions and CI:"
|
||||
"https://www.tianocore.org/tianocore-wiki.github.io/development/coding-standards/edk_ii_code_formatting.html\n")
|
||||
"https://www.tianocore.org/tianocore-wiki.github.io/development/coding-standards/edk_ii_code_formatting.html\n"
|
||||
)
|
||||
|
||||
if self._output_file_diffs:
|
||||
logging.info("Calculating file diffs. This might take a while...")
|
||||
|
||||
for formatted_file in formatted_files:
|
||||
pre_formatted_file = formatted_file[:-len(UncrustifyCheck.FORMATTED_FILE_EXTENSION)]
|
||||
pre_formatted_file = formatted_file[
|
||||
: -len(UncrustifyCheck.FORMATTED_FILE_EXTENSION)
|
||||
]
|
||||
|
||||
logging.error(f"Formatting errors in {os.path.relpath(pre_formatted_file, self._abs_package_path)}")
|
||||
self._tc.LogStdError(f"Formatting errors in {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n")
|
||||
logging.error(
|
||||
f"Formatting errors in {os.path.relpath(pre_formatted_file, self._abs_package_path)}"
|
||||
)
|
||||
self._tc.LogStdError(
|
||||
f"Formatting errors in {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n"
|
||||
)
|
||||
|
||||
if (self._output_file_diffs or
|
||||
self._file_template_contents is not None or
|
||||
self._func_template_contents is not None):
|
||||
if (
|
||||
self._output_file_diffs
|
||||
or self._file_template_contents is not None
|
||||
or self._func_template_contents is not None
|
||||
):
|
||||
|
||||
with open(formatted_file) as ff:
|
||||
formatted_file_text = ff.read()
|
||||
|
||||
if (self._file_template_contents is not None and
|
||||
self._file_template_contents in formatted_file_text):
|
||||
logging.info(f"File header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}")
|
||||
self._tc.LogStdError(f"File header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n")
|
||||
if (
|
||||
self._file_template_contents is not None
|
||||
and self._file_template_contents in formatted_file_text
|
||||
):
|
||||
logging.info(
|
||||
f"File header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}"
|
||||
)
|
||||
self._tc.LogStdError(
|
||||
f"File header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n"
|
||||
)
|
||||
|
||||
if (self._func_template_contents is not None and
|
||||
self._func_template_contents in formatted_file_text):
|
||||
logging.info(f"A function header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}")
|
||||
self._tc.LogStdError(f"A function header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n")
|
||||
if (
|
||||
self._func_template_contents is not None
|
||||
and self._func_template_contents in formatted_file_text
|
||||
):
|
||||
logging.info(
|
||||
f"A function header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}"
|
||||
)
|
||||
self._tc.LogStdError(
|
||||
f"A function header is missing in {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n"
|
||||
)
|
||||
|
||||
if self._output_file_diffs:
|
||||
with open(pre_formatted_file) as pf:
|
||||
pre_formatted_file_text = pf.read()
|
||||
|
||||
for line in difflib.unified_diff(pre_formatted_file_text.split('\n'), formatted_file_text.split('\n'), fromfile=pre_formatted_file, tofile=formatted_file, n=3):
|
||||
for line in difflib.unified_diff(
|
||||
pre_formatted_file_text.split("\n"),
|
||||
formatted_file_text.split("\n"),
|
||||
fromfile=pre_formatted_file,
|
||||
tofile=formatted_file,
|
||||
n=3,
|
||||
):
|
||||
logging.error(line)
|
||||
self._tc.LogStdError(line)
|
||||
|
||||
logging.error('\n')
|
||||
self._tc.LogStdError('\n')
|
||||
logging.error("\n")
|
||||
self._tc.LogStdError("\n")
|
||||
|
||||
def _remove_tree(self, dir_path: str, ignore_errors: bool = False) -> None:
|
||||
"""
|
||||
|
|
@ -664,7 +805,9 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
|
||||
for _ in range(3): # retry up to 3 times
|
||||
try:
|
||||
shutil.rmtree(dir_path, ignore_errors=ignore_errors, onerror=_remove_readonly)
|
||||
shutil.rmtree(
|
||||
dir_path, ignore_errors=ignore_errors, onerror=_remove_readonly
|
||||
)
|
||||
except OSError as err:
|
||||
logging.warning(f"Failed to fully remove {dir_path}: {err}")
|
||||
else:
|
||||
|
|
@ -688,4 +831,5 @@ class UncrustifyCheck(ICiBuildPlugin):
|
|||
|
||||
if self._app_exit_code != 0 and self._app_exit_code != 1:
|
||||
raise UncrustifyAppExecutionException(
|
||||
f"Error {str(self._app_exit_code)} returned from Uncrustify:\n\n{str(self._app_output)}")
|
||||
f"Error {str(self._app_exit_code)} returned from Uncrustify:\n\n{str(self._app_output)}"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue