From 392f87aeb6b45e2f46753474a4a25d80d345a1ba Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Wed, 9 Nov 2022 18:27:17 -0500 Subject: [PATCH] Edk2Path: Add an env variable to allow nested packages (#199) Adds an environment variable called `STUART_IGNORE_EDK_NESTED_PACKAGES` that a platform can set to `"true"` to allow nested packages. Nested packages are a violation of EDK II package rules and should be fixed. This is provided for backward compatibility and temporary use until the variable is no longer needed. Signed-off-by: Michael Kubacki --- edk2toollib/uefi/edk2/path_utilities.py | 39 +++++++++++++++++--- edk2toollib/uefi/edk2/test_path_utilities.py | 11 ++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/edk2toollib/uefi/edk2/path_utilities.py b/edk2toollib/uefi/edk2/path_utilities.py index 6c51b76d..ac213edc 100644 --- a/edk2toollib/uefi/edk2/path_utilities.py +++ b/edk2toollib/uefi/edk2/path_utilities.py @@ -100,17 +100,46 @@ def __init__(self, ws: os.PathLike, package_path_list: Iterable[os.PathLike], package_path_packages[package_path] = \ [Path(p).parent for p in package_path.glob('**/*.dec')] + # Note: The ability to ignore this function raising an exception on + # nested packages is temporary. Do not plan on this variable + # being available long-term and try to resolve the nested + # packages problem right away. + # + # Removal is tracked in the following GitHub issue: + # https://github.com/tianocore/edk2-pytool-library/issues/200 + ignore_nested_packages = False + if "PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES" in os.environ and \ + os.environ["PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES"].strip().lower() == \ + "true": + ignore_nested_packages = True + for package_path, packages in package_path_packages.items(): for i, package in enumerate(packages): for j in range(i + 1, len(packages)): comp_package = packages[j] - if (package.is_relative_to(comp_package) or comp_package.is_relative_to(package)): - raise Exception( - f"Nested packages not allowed. The packages " - f"[{str(package)}] and [{str(comp_package)}] are " - f"nested") + if ignore_nested_packages: + self.logger.log( + logging.WARNING, + f"Nested packages not allowed. The packages " + f"[{str(package)}] and [{str(comp_package)}] are " + f"nested.") + self.logger.log( + logging.WARNING, + "Note 1: Nested packages are being ignored right now because the " + "\"PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES\" environment variable " + "is set. Do not depend on this variable long-term.") + self.logger.log( + logging.WARNING, + "Note 2: Some pytool features may not work as expected with nested packages.") + else: + raise Exception( + f"Nested packages not allowed. The packages " + f"[{str(package)}] and [{str(comp_package)}] are " + f"nested. Set the \"PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES\" " + f"environment variable to \"true\" as a temporary workaround " + f"until you fix the packages so they are no longer nested.") def GetEdk2RelativePathFromAbsolutePath(self, abspath): """Given an absolute path return a edk2 path relative to workspace or packagespath. diff --git a/edk2toollib/uefi/edk2/test_path_utilities.py b/edk2toollib/uefi/edk2/test_path_utilities.py index e46d6e1a..dbc6360b 100644 --- a/edk2toollib/uefi/edk2/test_path_utilities.py +++ b/edk2toollib/uefi/edk2/test_path_utilities.py @@ -811,9 +811,20 @@ def test_get_relative_path_with_nested_packages(self): pp2_name = "PPTestPkg2" self._make_edk2_package_helper(folder_pp2_abs, pp2_name) + # Nested packages should raise an exception by default self.assertRaises(Exception, Edk2Path, folder_ws_abs, [folder_pp1_abs]) self.assertRaises(Exception, Edk2Path, folder_ws_abs, [folder_pp1_abs, folder_pp2_abs]) + # Nested packages should no longer raise an exception + # Note: These tests can be removed when support for + # PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES is removed. + os.environ["PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES"] = "true" + Edk2Path(folder_ws_abs, [folder_pp1_abs]) + Edk2Path(folder_ws_abs, [folder_pp1_abs, folder_pp2_abs]) + + # Remove the environment variable now that the test above is complete + os.environ.pop("PYTOOL_TEMPORARILY_IGNORE_NESTED_EDK_PACKAGES") + def test_get_relative_path_when_folder_is_next_to_package(self): ''' test usage of GetEdk2RelativePathFromAbsolutePath when a folder containing a package is in the same directory as a different package. This test ensures the correct value is returned regardless the order of