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)
 |