BZ:https://bugzilla.tianocore.org/show_bug.cgi?id=1815 The edk2 source tree contains four instances of the outdated mailing list address "edk2-devel@lists.01.org". I created a new variable, MSG_EDKII_MAIL_ADDR, to receive the new email address and replaced the old one with this variable Cc: Bob Feng <bob.c.feng@intel.com> Cc: Liming Gao <liming.gao@intel.com> Signed-off-by: Zhiju.Fan <zhijux.fan@intel.com> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
		
			
				
	
	
		
			271 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # Install distribution package.
 | |
| #
 | |
| # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| #
 | |
| # SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| #
 | |
| 
 | |
| '''
 | |
| RmPkg
 | |
| '''
 | |
| 
 | |
| ##
 | |
| # Import Modules
 | |
| #
 | |
| import os.path
 | |
| from stat import S_IWUSR
 | |
| from traceback import format_exc
 | |
| from platform import python_version
 | |
| from hashlib import md5
 | |
| from sys import stdin
 | |
| from sys import platform
 | |
| 
 | |
| from Core.DependencyRules import DependencyRules
 | |
| from Library import GlobalData
 | |
| from Logger import StringTable as ST
 | |
| import Logger.Log as Logger
 | |
| from Logger.ToolError import OPTION_MISSING
 | |
| from Logger.ToolError import UNKNOWN_ERROR
 | |
| from Logger.ToolError import ABORT_ERROR
 | |
| from Logger.ToolError import CODE_ERROR
 | |
| from Logger.ToolError import FatalError
 | |
| 
 | |
| 
 | |
| ## CheckDpDepex
 | |
| #
 | |
| # Check if the Depex is satisfied
 | |
| # @param Dep: Dep
 | |
| # @param Guid: Guid of Dp
 | |
| # @param Version: Version of Dp
 | |
| # @param WorkspaceDir: Workspace Dir
 | |
| #
 | |
| def CheckDpDepex(Dep, Guid, Version, WorkspaceDir):
 | |
|     (Removable, DependModuleList) = Dep.CheckDpDepexForRemove(Guid, Version)
 | |
|     if not Removable:
 | |
|         Logger.Info(ST.MSG_CONFIRM_REMOVE)
 | |
|         Logger.Info(ST.MSG_USER_DELETE_OP)
 | |
|         Input = stdin.readline()
 | |
|         Input = Input.replace('\r', '').replace('\n', '')
 | |
|         if Input.upper() != 'Y':
 | |
|             Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
 | |
|             return 1
 | |
|         else:
 | |
|             #
 | |
|             # report list of modules that are not valid due to force
 | |
|             # remove,
 | |
|             # also generate a log file for reference
 | |
|             #
 | |
|             Logger.Info(ST.MSG_INVALID_MODULE_INTRODUCED)
 | |
|             LogFilePath = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gINVALID_MODULE_FILE))
 | |
|             Logger.Info(ST.MSG_CHECK_LOG_FILE % LogFilePath)
 | |
|             try:
 | |
|                 LogFile = open(LogFilePath, 'w')
 | |
|                 try:
 | |
|                     for ModulePath in DependModuleList:
 | |
|                         LogFile.write("%s\n"%ModulePath)
 | |
|                         Logger.Info(ModulePath)
 | |
|                 except IOError:
 | |
|                     Logger.Warn("\nRmPkg", ST.ERR_FILE_WRITE_FAILURE,
 | |
|                                 File=LogFilePath)
 | |
|             except IOError:
 | |
|                 Logger.Warn("\nRmPkg", ST.ERR_FILE_OPEN_FAILURE,
 | |
|                             File=LogFilePath)
 | |
|             finally:
 | |
|                 LogFile.close()
 | |
| 
 | |
| ## Remove Path
 | |
| #
 | |
| # removing readonly file on windows will get "Access is denied"
 | |
| # error, so before removing, change the mode to be writeable
 | |
| #
 | |
| # @param Path: The Path to be removed
 | |
| #
 | |
| def RemovePath(Path):
 | |
|     Logger.Info(ST.MSG_REMOVE_FILE % Path)
 | |
|     if not os.access(Path, os.W_OK):
 | |
|         os.chmod(Path, S_IWUSR)
 | |
|     os.remove(Path)
 | |
|     try:
 | |
|         os.removedirs(os.path.split(Path)[0])
 | |
|     except OSError:
 | |
|         pass
 | |
| ## GetCurrentFileList
 | |
| #
 | |
| # @param DataBase: DataBase of UPT
 | |
| # @param Guid: Guid of Dp
 | |
| # @param Version: Version of Dp
 | |
| # @param WorkspaceDir: Workspace Dir
 | |
| #
 | |
| def GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir):
 | |
|     NewFileList = []
 | |
|     for Dir in  DataBase.GetDpInstallDirList(Guid, Version):
 | |
|         RootDir = os.path.normpath(os.path.join(WorkspaceDir, Dir))
 | |
|         for Root, Dirs, Files in os.walk(RootDir):
 | |
|             Logger.Debug(0, Dirs)
 | |
|             for File in Files:
 | |
|                 FilePath = os.path.join(Root, File)
 | |
|                 if FilePath not in NewFileList:
 | |
|                     NewFileList.append(FilePath)
 | |
|     return NewFileList
 | |
| 
 | |
| 
 | |
| ## Tool entrance method
 | |
| #
 | |
| # This method mainly dispatch specific methods per the command line options.
 | |
| # If no error found, return zero value so the caller of this tool can know
 | |
| # if it's executed successfully or not.
 | |
| #
 | |
| # @param  Options: command option
 | |
| #
 | |
| def Main(Options = None):
 | |
| 
 | |
|     try:
 | |
|         DataBase = GlobalData.gDB
 | |
|         if not Options.DistributionFile:
 | |
|             Logger.Error("RmPkg",
 | |
|                          OPTION_MISSING,
 | |
|                          ExtraData=ST.ERR_SPECIFY_PACKAGE)
 | |
|         WorkspaceDir = GlobalData.gWORKSPACE
 | |
|         #
 | |
|         # Prepare check dependency
 | |
|         #
 | |
|         Dep = DependencyRules(DataBase)
 | |
| 
 | |
|         #
 | |
|         # Get the Dp information
 | |
|         #
 | |
|         StoredDistFile, Guid, Version = GetInstalledDpInfo(Options.DistributionFile, Dep, DataBase, WorkspaceDir)
 | |
| 
 | |
|         #
 | |
|         # Check Dp depex
 | |
|         #
 | |
|         CheckDpDepex(Dep, Guid, Version, WorkspaceDir)
 | |
| 
 | |
|         #
 | |
|         # remove distribution
 | |
|         #
 | |
|         RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, Options.Yes)
 | |
| 
 | |
|         Logger.Quiet(ST.MSG_FINISH)
 | |
| 
 | |
|         ReturnCode = 0
 | |
| 
 | |
|     except FatalError as XExcept:
 | |
|         ReturnCode = XExcept.args[0]
 | |
|         if Logger.GetLevel() <= Logger.DEBUG_9:
 | |
|             Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
 | |
|                          format_exc())
 | |
|     except KeyboardInterrupt:
 | |
|         ReturnCode = ABORT_ERROR
 | |
|         if Logger.GetLevel() <= Logger.DEBUG_9:
 | |
|             Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
 | |
|                          format_exc())
 | |
|     except:
 | |
|         Logger.Error(
 | |
|                     "\nRmPkg",
 | |
|                     CODE_ERROR,
 | |
|                     ST.ERR_UNKNOWN_FATAL_REMOVING_ERR,
 | |
|                     ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR,
 | |
|                     RaiseError=False
 | |
|                     )
 | |
|         Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
 | |
|                      format_exc())
 | |
|         ReturnCode = CODE_ERROR
 | |
|     return ReturnCode
 | |
| 
 | |
| ## GetInstalledDpInfo method
 | |
| #
 | |
| # Get the installed distribution information
 | |
| #
 | |
| # @param  DistributionFile: the name of the distribution
 | |
| # @param  Dep: the instance of DependencyRules
 | |
| # @param  DataBase: the internal database
 | |
| # @param  WorkspaceDir: work space directory
 | |
| # @retval StoredDistFile: the distribution file that backed up
 | |
| # @retval Guid: the Guid of the distribution
 | |
| # @retval Version: the Version of distribution
 | |
| #
 | |
| def GetInstalledDpInfo(DistributionFile, Dep, DataBase, WorkspaceDir):
 | |
|     (Guid, Version, NewDpFileName) = DataBase.GetDpByName(os.path.split(DistributionFile)[1])
 | |
|     if not Guid:
 | |
|         Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_PACKAGE_NOT_INSTALLED % DistributionFile)
 | |
| 
 | |
|     #
 | |
|     # Check Dp existing
 | |
|     #
 | |
|     if not Dep.CheckDpExists(Guid, Version):
 | |
|         Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_DISTRIBUTION_NOT_INSTALLED)
 | |
|     #
 | |
|     # Check for Distribution files existence in /conf/upt, if not exist,
 | |
|     # Warn user and go on.
 | |
|     #
 | |
|     StoredDistFile = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR, NewDpFileName))
 | |
|     if not os.path.isfile(StoredDistFile):
 | |
|         Logger.Warn("RmPkg", ST.WRN_DIST_NOT_FOUND%StoredDistFile)
 | |
|         StoredDistFile = None
 | |
| 
 | |
|     return StoredDistFile, Guid, Version
 | |
| 
 | |
| ## RemoveDist method
 | |
| #
 | |
| # remove a distribution
 | |
| #
 | |
| # @param  Guid: the Guid of the distribution
 | |
| # @param  Version: the Version of distribution
 | |
| # @param  StoredDistFile: the distribution file that backed up
 | |
| # @param  DataBase: the internal database
 | |
| # @param  WorkspaceDir: work space directory
 | |
| # @param  ForceRemove: whether user want to remove file even it is modified
 | |
| #
 | |
| def RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, ForceRemove):
 | |
|     #
 | |
|     # Get Current File List
 | |
|     #
 | |
|     NewFileList = GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir)
 | |
| 
 | |
|     #
 | |
|     # Remove all files
 | |
|     #
 | |
|     MissingFileList = []
 | |
|     for (Path, Md5Sum) in DataBase.GetDpFileList(Guid, Version):
 | |
|         if os.path.isfile(Path):
 | |
|             if Path in NewFileList:
 | |
|                 NewFileList.remove(Path)
 | |
|             if not ForceRemove:
 | |
|                 #
 | |
|                 # check whether modified by users
 | |
|                 #
 | |
|                 Md5Signature = md5(open(str(Path), 'rb').read())
 | |
|                 if Md5Sum != Md5Signature.hexdigest():
 | |
|                     Logger.Info(ST.MSG_CONFIRM_REMOVE2 % Path)
 | |
|                     Input = stdin.readline()
 | |
|                     Input = Input.replace('\r', '').replace('\n', '')
 | |
|                     if Input.upper() != 'Y':
 | |
|                         continue
 | |
|             RemovePath(Path)
 | |
|         else:
 | |
|             MissingFileList.append(Path)
 | |
| 
 | |
|     for Path in NewFileList:
 | |
|         if os.path.isfile(Path):
 | |
|             if (not ForceRemove) and (not os.path.split(Path)[1].startswith('.')):
 | |
|                 Logger.Info(ST.MSG_CONFIRM_REMOVE3 % Path)
 | |
|                 Input = stdin.readline()
 | |
|                 Input = Input.replace('\r', '').replace('\n', '')
 | |
|                 if Input.upper() != 'Y':
 | |
|                     continue
 | |
|             RemovePath(Path)
 | |
| 
 | |
|     #
 | |
|     # Remove distribution files in /Conf/.upt
 | |
|     #
 | |
|     if StoredDistFile is not None:
 | |
|         os.remove(StoredDistFile)
 | |
| 
 | |
|     #
 | |
|     # update database
 | |
|     #
 | |
|     Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE)
 | |
|     DataBase.RemoveDpObj(Guid, Version)
 |