.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:
Michael Kubacki 2026-07-31 12:24:02 -04:00 committed by mergify[bot]
parent 4074b5db5d
commit e0d2cb29fe

View file

@ -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)}"
)