From 6f49d15826ca669d9b3803ab4d050b208a622ffc Mon Sep 17 00:00:00 2001 From: Nishanth Sanjeevi Date: Mon, 29 Jul 2024 21:41:45 +0530 Subject: [PATCH] Add deprecation warning support to OverrideValidation plugin (#742) Added deprecation warning support to the existing Override validation plugin/tool. - [ ] Impacts functionality? - **Functionality** - All libraries/drivers that are no longer used should add a Deprecation warning - [ ] Impacts security? - **Security** - N/A - [ ] Breaking change? - **Breaking change** - Will anyone consuming this change experience a break in build or boot behavior? No - [ ] Includes tests? No - [ ] Includes documentation? Added documentation for how to use the Deprecation warnings module Added the Deprecation warnings to the INFs and a warning was thrown when a deprecated module was part of the DSC N/A --- .../OverrideValidation/OverrideValidation.py | 215 ++++++++++++++---- .../OverrideValidation_plug_in.json | 2 +- BaseTools/Plugin/OverrideValidation/ReadMe.md | 44 +++- 3 files changed, 212 insertions(+), 49 deletions(-) diff --git a/BaseTools/Plugin/OverrideValidation/OverrideValidation.py b/BaseTools/Plugin/OverrideValidation/OverrideValidation.py index 081a0320ed..dcb5b8f8a3 100644 --- a/BaseTools/Plugin/OverrideValidation/OverrideValidation.py +++ b/BaseTools/Plugin/OverrideValidation/OverrideValidation.py @@ -3,7 +3,9 @@ # This tool depends on EDK2 and will parse dsc files, inf files and other standard # EDK2 assets # -# Copyright (c) Microsoft Corporation. +# This tool also generates deprecation warnings if a given file is deprecated +# +# Copyright (c) Microsoft Corporation. All rights reserved. # SPDX-License-Identifier: BSD-2-Clause-Patent ## @@ -15,7 +17,7 @@ import os import re import sys -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta from io import StringIO # @@ -32,20 +34,24 @@ from edk2toollib.utility_functions import RunCmd #Tuple for (version, entrycount) - FORMAT_VERSION_1 = (1, 4) #Version 1: #OVERRIDE : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss - FORMAT_VERSION_2 = (2, 5) #Version 2: #OVERRIDE : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss | GIT_COMMIT - FORMAT_VERSIONS = [FORMAT_VERSION_1, FORMAT_VERSION_2] - + OVERRIDE_FORMAT_VERSION_1 = (1, 4) #Version 1: #OVERRIDE : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss + OVERRIDE_FORMAT_VERSION_2 = (2, 5) #Version 2: #OVERRIDE : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss | GIT_COMMIT + DEPRECATION_FORMAT_VERSION_1 = (1, 4) # Version 1: # DEPRECATED : VERSION | PATH_TO_NEW_MODULE_TO_USE | YYYY-MM-DDThh-mm-ss | DEPRECATION_TIMELINE + FORMAT_VERSIONS = [OVERRIDE_FORMAT_VERSION_1, OVERRIDE_FORMAT_VERSION_2, DEPRECATION_FORMAT_VERSION_1] + TIMESTAMP_FORMAT = "%Y-%m-%dT%H-%M-%S" class OverrideValidation(IUefiBuildPlugin): class OverrideResult(object): OR_ALL_GOOD = 0 + DR_ALL_GOOD = 0 OR_FILE_CHANGE = 1 OR_VER_UNRECOG = 2 OR_INVALID_FORMAT = 3 OR_DSC_INF_NOT_FOUND = 4 OR_TARGET_INF_NOT_FOUND = 5 + DR_DEPRECATION_WARNING = 6 + DR_DEPRECATED_ERROR = 7 @classmethod def GetErrStr (cls, errcode): @@ -62,6 +68,10 @@ def GetErrStr (cls, errcode): str = 'FILE_NOT_FOUND' elif (errcode == cls.OR_TARGET_INF_NOT_FOUND): str = 'INF_FILE_NOT_FOUND' + elif (errcode == cls.DR_DEPRECATION_WARNING): + str = 'DEPRECATION_WARNING' + elif (errcode == cls.DR_DEPRECATED_ERROR): + str = 'DEPRECATED_ERROR' else: str = 'UNKNOWN' return str @@ -81,22 +91,22 @@ def __init__(self, path, status, age): def do_pre_build(self, thebuilder): # Setup timestamp to log time cost in this section starttime = datetime.now() - logging.info("---------------------------------------------------------") - logging.info("--------------Override Validation Starting---------------") - logging.info("---------------------------------------------------------") + logging.info("---------------------------------------------------------------------") + logging.info("--------------Override/Deprecation Validation Starting---------------") + logging.info("---------------------------------------------------------------------") rc = self.override_plat_validate(thebuilder) if(rc == self.OverrideResult.OR_ALL_GOOD): - logging.debug("Override validation all in sync") + logging.debug("Override/Deprecation validation all in sync") else: - logging.error("Override validation failed") + logging.error("Override/Deprecation validation failed") endtime = datetime.now() delta = endtime - starttime - logging.info("---------------------------------------------------------") - logging.info("--------------Override Validation Finished---------------") - logging.info("-------------- Running Time (mm:ss): {0[0]:02}:{0[1]:02} --------------".format(divmod(delta.seconds, 60))) - logging.info("---------------------------------------------------------") + logging.info("----------------------------------------------------------------------") + logging.info("--------------Override/Deprecation Validation Finished----------------") + logging.info("-------------- Running Time (mm:ss): {0[0]:02}:{0[1]:02} -------------".format(divmod(delta.seconds, 60))) + logging.info("----------------------------------------------------------------------") return rc # END: do_pre_build(self, thebuilder) @@ -128,7 +138,7 @@ def override_plat_validate(self, thebuilder): if m_result != self.OverrideResult.OR_ALL_GOOD: if m_result != self.OverrideResult.OR_DSC_INF_NOT_FOUND: result = m_result - logging.error("Override processing error %s in file/dir %s" % (self.OverrideResult.GetErrStr(m_result), file)) + logging.error("Override/Deprecation processing error %s in file/dir %s" % (self.OverrideResult.GetErrStr(m_result), file)) self.override_log_print(thebuilder, modulelist, status) @@ -176,20 +186,21 @@ def override_detect_process(self, thebuilder, filepath, filelist, modulenode, st CommentLine = Line.strip('#').split(':') if (len(CommentLine) != 2) or\ ((CommentLine[0].strip().lower() != 'override') and\ - (CommentLine[0].strip().lower() != 'track')): + (CommentLine[0].strip().lower() != 'track') and + (CommentLine[0].strip().lower() != 'deprecated')): continue # Process the override content, 1. Bail on bad data; 2. Print on formatted data (matched or not) tagtype = CommentLine[0].strip().lower() m_result = self.override_process_line(thebuilder, CommentLine[1], filepath, filelist, modulenode, status, tagtype) - if CommentLine[0].strip().lower() == 'override': + if tagtype == 'override': # For override tags, the hash has to match if m_result != self.OverrideResult.OR_ALL_GOOD: result = m_result logging.error("At Line %d: %s" %(lineno, Line)) - elif CommentLine[0].strip().lower() == 'track': + elif tagtype == 'track': # For track tags, ignore the tags of which inf modules are not found trackno = trackno + 1 if m_result == self.OverrideResult.OR_TARGET_INF_NOT_FOUND: @@ -204,6 +215,13 @@ def override_detect_process(self, thebuilder, filepath, filelist, modulenode, st else: track_ag.append(modulenode.reflist[-1].path) + elif tagtype == 'deprecated': + if m_result == self.OverrideResult.DR_DEPRECATION_WARNING: + logging.warning("At Line %d: %s" %(lineno, Line)) + elif m_result == self.OverrideResult.DR_DEPRECATED_ERROR: + logging.error("At Line %d: %s" %(lineno, Line)) + result = m_result + if trackno != 0 and len(track_nf) == trackno: # All track tags in this file are not found, this will enforce a failure, if not already failed if result == self.OverrideResult.OR_ALL_GOOD: @@ -276,7 +294,10 @@ def override_process_line(self, thebuilder, overridecnt, filepath, filelist, mod return result if version_match[0] == 1: - return self.override_process_line_with_version1(thebuilder, filelist, OverrideEntry, m_node, status, tagtype) + if tagtype == 'deprecated': + return self.deprecation_process_line_with_version1(thebuilder, filepath, OverrideEntry) + else: + return self.override_process_line_with_version1(thebuilder, filelist, OverrideEntry, m_node, status, tagtype) elif version_match[0] == 2: return self.override_process_line_with_version2(thebuilder, filelist, OverrideEntry, m_node, status, tagtype) else: @@ -303,7 +324,7 @@ def override_process_line_with_version1(self, thebuilder, filelist, OverrideEntr # Step 4: Parse the time of hash generation try: - EntryTimestamp = datetime.strptime(OverrideEntry[3].strip(), "%Y-%m-%dT%H-%M-%S") + EntryTimestamp = datetime.strptime(OverrideEntry[3].strip(), TIMESTAMP_FORMAT) EntryTimestamp = EntryTimestamp.replace(tzinfo=timezone.utc) except ValueError: logging.error("Inf Override Parse Error, override parameter has invalid timestamp %s" %(OverrideEntry[3].strip())) @@ -366,6 +387,65 @@ def override_process_line_with_version2(self, thebuilder, filelist, OverrideEntr return result # END: override_process_line_version2(self, thebuilder, filelist, OverrideEntry, m_node, status) + def deprecation_process_line_with_version1(self, thebuilder, filepath, DeprecationEntry): + """ + This method checks if a module is deprecated. + If the module is deprecated, it checks if the deprecation date has passed. + If current date is greater than the deprecation date, the build is failed. + Otherwise, a warning is thrown. + + If a older platform uses a deprecated module, it can add the deprecated module to a skip list + """ + + normalized_file_path = filepath.replace("\\", "/") + + # Check if the module is part of the skip list + skip_list_str = thebuilder.env.GetValue("DEPRECATED_MODULES_SKIPLIST") + + # Skip the modules that are part of skiplist + if skip_list_str is not None: + skip_list = skip_list_str.split(";") + for skipped_module in skip_list: + if skipped_module.strip() == "": + continue + + skipped_module_path = skipped_module.strip().replace("\\", "/") + if normalized_file_path.endswith(skipped_module_path): + logging.info("Use of Deprecated module: %s skipped as part of platform skip list", filepath) + return self.OverrideResult.DR_ALL_GOOD + + # Check if the module has passed the deprecation date + deprecation_timeline = int(DeprecationEntry[3]) + deprecation_dt = datetime.strptime(DeprecationEntry[2].strip(), TIMESTAMP_FORMAT).replace(tzinfo=timezone.utc) + timedelta(days=deprecation_timeline) + current_dt = datetime.now(timezone.utc) + + # Check if replacement file exists + if DeprecationEntry[1].strip() == "REMOVED_COMPLETELY": + replacement_path = None + else: + replacement_path = thebuilder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(DeprecationEntry[1].strip()) + + # Module has crossed date of deprecation + if current_dt > deprecation_dt: + logging.error("Use of Deprecated module: %s post date of deprecation.", filepath) + if replacement_path is None: + logging.error("Please remove the module (or) Add to DEPRECATED_MODULES_SKIPLIST") + else: + logging.error("Replace with: %s (or) Add to DEPRECATED_MODULES_SKIPLIST", replacement_path) + + return self.OverrideResult.DR_DEPRECATED_ERROR + + # Module is not deprecated yet + else: + logging.warning("Use of Deprecated module: %s.", filepath) + + if replacement_path is None: + logging.warning("Please remove the module (or) Add to DEPRECATED_MODULES_SKIPLIST before %s", deprecation_dt.strftime(TIMESTAMP_FORMAT)) + else: + logging.warning("Replace with: %s (or) Add to DEPRECATED_MODULES_SKIPLIST before %s", deprecation_dt.strftime(TIMESTAMP_FORMAT)) + + return self.OverrideResult.DR_DEPRECATION_WARNING + # Check override record against parsed entries # version: Override record's version number, normally parsed from the override record line # hash: Override record's hash field, normally parsed from the override record line, calculated by the standalone ModuleHash tool @@ -375,7 +455,7 @@ def override_hash_compare(self, thebuilder, version, hash, fullpath): hash_val = '' # Error out the unknown version - if (version == FORMAT_VERSION_1[0]): + if (version == OVERRIDE_FORMAT_VERSION_1[0]): hash_val = ModuleHashCal(fullpath) if (hash_val != hash): result = self.OverrideResult.OR_FILE_CHANGE @@ -402,7 +482,7 @@ def override_log_print(self, thebuilder, modulelist, status): with open(logfile, 'w') as log: log.write("Platform: %s\n" %(thebuilder.env.GetValue("PRODUCT_NAME"))) log.write("Version: %s\n" %(thebuilder.env.GetValue("BLD_*_BUILDID_STRING"))) - log.write("Date: %s\n" %(datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%S"))) + log.write("Date: %s\n" %(datetime.now(timezone.utc).strftime(TIMESTAMP_FORMAT))) log.write("Commit: %s\n" %(thebuilder.env.GetValue("BLD_*_BUILDSHA"))) log.write("State: %d/%d\n" %(status[0], status[1])) @@ -582,6 +662,18 @@ def path_parse(): '-r', '--regenpath', dest = 'RegenPath', type=str, help = '''Specify the absolute path to an inf with existing overrides to regen by passing r Path/To/Target or --regenpath Path/To/Target.''' ) + group.add_argument ( + '-d', '--deprecatepath', dest = 'DeprecatedPath', type=str, default=None, + help = '''Specify the absolute path to the file to be deprecated by passing -d DEPRECATED_MODULE_PATH or --deprecatepath DEPRECATED_MODULE_PATH.''' + ) + parser.add_argument ( + '-dr', '--deprecationreplacementpath', dest = 'DeprecationReplacementPath', type=str, default=None, + help = '''Specify the relative path from the package to the replacement module by passing -dr Path/To/ReplacementPath or --deprecationreplacementpath Path/To/Target.''' + ) + parser.add_argument ( + '-dt', '--deprecationtimeline', dest = 'DeprecationTimelineInDays', type=int, default=90, + help = '''Specify the deprecation timeline in days. default is 90 days.''' + ) parser.add_argument ( '-p', '--packagepath', dest = 'RegenPackagePath', nargs="*", default=[], help = '''Specify the packages path to be used to resolve relative paths when using --regenpath. ignored otherwise. Workspace is always included.''' @@ -608,7 +700,7 @@ def path_parse(): if not os.path.isfile(Paths.TargetPath): raise RuntimeError("Module path is invalid.") - if Paths.Version < 1 or Paths.Version > len(FORMAT_VERSIONS): + if Paths.Version not in [version_format[0] for version_format in FORMAT_VERSIONS]: raise RuntimeError("Version is invalid") if not os.path.isdir(Paths.WorkSpace): @@ -631,6 +723,15 @@ def path_parse(): if not os.path.normcase(Paths.RegenPath).startswith(os.path.normcase(Paths.WorkSpace.rstrip(os.sep)) + os.sep): raise RuntimeError("Module is not within specified Workspace.") + if Paths.DeprecatedPath is not None: + if not os.path.isfile(Paths.DeprecatedPath): + raise RuntimeError(f"Deprecation path {Paths.DeprecatedPath} module is invalid") + # Needs to strip os.sep is to take care of the root path case + # For a folder, this will do nothing on a formatted abspath + # For a drive root, this will rip off the os.sep + if not os.path.normcase(Paths.DeprecatedPath).startswith(os.path.normcase(Paths.WorkSpace.rstrip(os.sep)) + os.sep): + raise RuntimeError(f"Module {Paths.DeprecatedPath} is not within the specified Workspace {Paths.WorkSpace.rstrip(os.sep)}.") + return Paths ################################################ @@ -671,10 +772,10 @@ def path_parse(): VERSION_INDEX = Paths.Version - 1 if VERSION_INDEX == 0: - line = '#%s : %08d | %s | %s | %s\n' % (match.group(1), FORMAT_VERSION_1[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%S")) + line = '#%s : %08d | %s | %s | %s\n' % (match.group(1), OVERRIDE_FORMAT_VERSION_1[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime(TIMESTAMP_FORMAT)) elif VERSION_INDEX == 1: git_hash = ModuleGitHash(abs_path) - line = '#%s : %08d | %s | %s | %s | %s\n' % (match.group(1), FORMAT_VERSION_2[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%S"), git_hash) + line = '#%s : %08d | %s | %s | %s | %s\n' % (match.group(1), OVERRIDE_FORMAT_VERSION_2[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime(TIMESTAMP_FORMAT), git_hash) print("Updating:\n" + line) else: print(f"Warning: Could not resolve relative path {rel_path}. Override line not updated.\n") @@ -687,28 +788,52 @@ def path_parse(): else: dummy_list = [] pathtool = Edk2Path(Paths.WorkSpace, dummy_list) + if Paths.DeprecatedPath is not None: + # Generate deprecation warning line + # DEPRECATION_FORMAT_VERSION_1 = (1, 4) # Version 1: # DEPRECATED : VERSION | PATH_TO_NEW_MODULE_TO_USE | YYYY-MM-DDThh-mm-ss | DEPRECATION_TIMELINE + + if Paths.DeprecationReplacementPath is not None: + pkg_path = pathtool.GetContainingPackage(Paths.DeprecationReplacementPath) + if pkg_path is not None: + rel_path = Paths.DeprecationReplacementPath[Paths.DeprecationReplacementPath.find(pkg_path):] + else: + rel_path = pathtool.GetEdk2RelativePathFromAbsolutePath(Paths.DeprecationReplacementPath) + if not rel_path: + print(f"{Paths.DeprecationReplacementPath} is invalid for this workspace.") + sys.exit(1) + rel_path = rel_path.replace('\\', '/') + else: + rel_path = "REMOVED_COMPLETELY" + + print(f"The module will be deprecated in {Paths.DeprecationTimelineInDays} days") + print("Copy and paste the following line(s) to your deprecated inf file(s):\n") + print('#%s : %08d | %s | %s | %s\n' % ('Deprecated', DEPRECATION_FORMAT_VERSION_1[0], rel_path, + datetime.now(timezone.utc).strftime(TIMESTAMP_FORMAT), str(Paths.DeprecationTimelineInDays))) - # Generate and print the override for pasting into the file. - # Use absolute module path to find package path - pkg_path = pathtool.GetContainingPackage(Paths.TargetPath) - if pkg_path is not None: - rel_path = Paths.TargetPath[Paths.TargetPath.find(pkg_path):] else: - rel_path = pathtool.GetEdk2RelativePathFromAbsolutePath(Paths.TargetPath) - if not rel_path: - print(f"{Paths.TargetPath} is invalid for this workspace.") - sys.exit(1) + # Generate override hash + + # Generate and print the override for pasting into the file. + # Use absolute module path to find package path + pkg_path = pathtool.GetContainingPackage(Paths.TargetPath) + if pkg_path is not None: + rel_path = Paths.TargetPath[Paths.TargetPath.find(pkg_path):] + else: + rel_path = pathtool.GetEdk2RelativePathFromAbsolutePath(Paths.TargetPath) + if not rel_path: + print(f"{Paths.TargetPath} is invalid for this workspace.") + sys.exit(1) - rel_path = rel_path.replace('\\', '/') - mod_hash = ModuleHashCal(Paths.TargetPath) + rel_path = rel_path.replace('\\', '/') + mod_hash = ModuleHashCal(Paths.TargetPath) - VERSION_INDEX = Paths.Version - 1 + VERSION_INDEX = Paths.Version - 1 - if VERSION_INDEX == 0: - print("Copy and paste the following line(s) to your overrider inf file(s):\n") - print('#%s : %08d | %s | %s | %s' % ("Override" if not Paths.Track else "Track", FORMAT_VERSION_1[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%S"))) + if VERSION_INDEX == 0: + print("Copy and paste the following line(s) to your overrider inf file(s):\n") + print('#%s : %08d | %s | %s | %s' % ("Override" if not Paths.Track else "Track", OVERRIDE_FORMAT_VERSION_1[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime(TIMESTAMP_FORMAT))) - elif VERSION_INDEX == 1: - git_hash = ModuleGitHash(Paths.TargetPath) - print("Copy and paste the following line(s) to your overrider inf file(s):\n") - print('#%s : %08d | %s | %s | %s | %s' % ("Override" if not Paths.Track else "Track", FORMAT_VERSION_2[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%S"), git_hash)) + elif VERSION_INDEX == 1: + git_hash = ModuleGitHash(Paths.TargetPath) + print("Copy and paste the following line(s) to your overrider inf file(s):\n") + print('#%s : %08d | %s | %s | %s | %s' % ("Override" if not Paths.Track else "Track", OVERRIDE_FORMAT_VERSION_2[0], rel_path, mod_hash, datetime.now(timezone.utc).strftime(TIMESTAMP_FORMAT), git_hash)) diff --git a/BaseTools/Plugin/OverrideValidation/OverrideValidation_plug_in.json b/BaseTools/Plugin/OverrideValidation/OverrideValidation_plug_in.json index 5d1e695acd..24a741f7ca 100644 --- a/BaseTools/Plugin/OverrideValidation/OverrideValidation_plug_in.json +++ b/BaseTools/Plugin/OverrideValidation/OverrideValidation_plug_in.json @@ -1,5 +1,5 @@ { "scope": "global", - "name": "Override Validation Pre Build Plugin", + "name": "Override Validation and Deprecation Warning Pre Build Plugin", "module": "OverrideValidation" } \ No newline at end of file diff --git a/BaseTools/Plugin/OverrideValidation/ReadMe.md b/BaseTools/Plugin/OverrideValidation/ReadMe.md index b3b9ac9e21..ccff927e06 100644 --- a/BaseTools/Plugin/OverrideValidation/ReadMe.md +++ b/BaseTools/Plugin/OverrideValidation/ReadMe.md @@ -102,6 +102,30 @@ Override record to be included in overriding module's inf: #Override : 00000002 | MdeModulePkg/Library/BaseSerialPortLib16550 | 140759cf30a73b02f48cc1f226b015d8 | 2021-12-07T05-30-10 | fa99a33fdb7e8bf6063513fddb807105ec2fad81 ``` +Command to generate a deprecation record: + +``` cmd +OverrideValidation.py -w C:\Repo -d C:\Repo\MU_BASECORE\MdeModulePkg\BaseMemoryLib\BaseMemoryLib.inf -dr C:\Repo\MU_BASECORE\MdeModulePkg\BaseMemoryLibV2\BaseMemoryLib.inf -dt 120 +``` + +Deprecation record to be included in the deprecated module's inf: + +``` cmd +#Deprecated : 00000001 | MdeModulePkg/BaseMemoryLibV2/BaseMemoryLib.inf | 2024-02-16T04-00-28 | 120 +``` + +Deprecation warning example: + +``` cmd +WARNING - Use of Deprecated module: C:\Repo\MU_BASECORE\MdeModulePkg\BaseMemoryLib\BaseMemoryLib.inf, Please switch to: C:\Repo\MU_BASECORE\MdeModulePkg\BaseMemoryLibV2\BaseMemoryLib.inf. +``` + +To disable Deprecation warnings for a given module, add it to the deprecation modules skip list. + +``` cmd +self.env.SetValue("DEPRECATED_MODULES_SKIPLIST", "MdeModulePkg\BaseMemoryLib\BaseMemoryLib.inf; MdeModulePkg\MemoryAllocationLib\MemoryAllocationLib.inf", "Skip list for platforms") +``` + Override log generated during pre-build process: ``` cmd @@ -151,17 +175,21 @@ index 2d4ca47299..90da207a39 100644 ## Versions -There are two versions of the override format. +There are two versions of the override format and one version of the deprecation format -### Version 1 +### Override Version 1 ``` cmd +OVERRIDE_FORMAT_VERSION_1 = (1, 4) # Version 1 +#Override : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss #Override : 00000001 | MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf | cc255d9de141fccbdfca9ad02e0daa47 | 2018-05-09T17-54-17 ``` -### Version 2 +### Override Version 2 ``` cmd +OVERRIDE_FORMAT_VERSION_2 = (2, 5) # Version 2 +#Override : VERSION | PATH_TO_MODULE | HASH | YYYY-MM-DDThh-mm-ss | GIT_COMMIT #Override : 00000002 | MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf | cc255d9de141fccbdfca9ad02e0daa47 | 2018-05-09T17-54-17 | 575096df6a ``` @@ -170,6 +198,16 @@ upstream was last updated. This allows to tools to do a `git diff` between what you currently have and what is in the tree. It currently only diffs the overridden file (the INF or DSC) and the overriding file. +### Deprecation Version 1 + +``` cmd +# DEPRECATION_FORMAT_VERSION_1 = (1, 4) # Version 1 +#Deprecated : VERSION | PATH_TO_NEW_MODULE_TO_USE | YYYY-MM-DDThh-mm-ss | DEPRECATION_TIMELINE + +example: +#Deprecated : 00000001 | MdeModulePkg/BaseMemoryLibV2/BaseMemoryLib.inf | 2024-02-16T04-00-28 | 90 +``` + ## Copyright & License Copyright (c) Microsoft Corporation.