Add a new function to test if a DIST file list one by one to see if they can meet the requirement of Dependency. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hess Chen <hesheng.chen@intel.com> Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
		
			
				
	
	
		
			344 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| #
 | |
| # This file is the main entry for UPT 
 | |
| #
 | |
| # Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
| #
 | |
| # This program and the accompanying materials are licensed and made available 
 | |
| # under the terms and conditions of the BSD License which accompanies this 
 | |
| # distribution. The full text of the license may be found at 
 | |
| # http://opensource.org/licenses/bsd-license.php
 | |
| #
 | |
| # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| #
 | |
| 
 | |
| '''
 | |
| UPT
 | |
| '''
 | |
| 
 | |
| ## import modules
 | |
| #
 | |
| from Core import FileHook
 | |
| import sys
 | |
| import os.path
 | |
| from sys import platform
 | |
| import platform as pf
 | |
| from optparse import OptionParser
 | |
| from traceback import format_exc
 | |
| from platform import python_version
 | |
| 
 | |
| from Logger import StringTable as ST
 | |
| import Logger.Log as Logger
 | |
| from Logger.StringTable import MSG_VERSION
 | |
| from Logger.StringTable import MSG_DESCRIPTION
 | |
| from Logger.StringTable import MSG_USAGE
 | |
| from Logger.ToolError import FILE_NOT_FOUND
 | |
| from Logger.ToolError import OPTION_MISSING
 | |
| from Logger.ToolError import FILE_TYPE_MISMATCH
 | |
| from Logger.ToolError import OPTION_CONFLICT
 | |
| from Logger.ToolError import FatalError
 | |
| from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR
 | |
| from Common.MultipleWorkspace import MultipleWorkspace as mws
 | |
| 
 | |
| import MkPkg
 | |
| import InstallPkg
 | |
| import RmPkg
 | |
| import InventoryWs
 | |
| import ReplacePkg
 | |
| import TestInstall
 | |
| from Library.Misc import GetWorkspace
 | |
| from Library import GlobalData
 | |
| from Core.IpiDb import IpiDatabase
 | |
| from BuildVersion import gBUILD_VERSION
 | |
| 
 | |
| ## CheckConflictOption
 | |
| #
 | |
| # CheckConflictOption
 | |
| #
 | |
| def CheckConflictOption(Opt):
 | |
|     if (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove or Opt.PackFileToReplace) \
 | |
|     and Opt.InventoryWs:
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_L_OA_EXCLUSIVE)
 | |
|     elif Opt.PackFileToReplace and (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove):
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_U_ICR_EXCLUSIVE)
 | |
|     elif (Opt.PackFileToCreate and Opt.PackFileToInstall and Opt.PackFileToRemove):
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_REQUIRE_I_C_R_OPTION)
 | |
|     elif Opt.PackFileToCreate and Opt.PackFileToInstall:
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_C_EXCLUSIVE)
 | |
|     elif Opt.PackFileToInstall and Opt.PackFileToRemove:
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_R_EXCLUSIVE)
 | |
|     elif Opt.PackFileToCreate and  Opt.PackFileToRemove:
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE)
 | |
|     elif Opt.TestDistFiles and (Opt.PackFileToCreate or Opt.PackFileToInstall \
 | |
|                                 or Opt.PackFileToRemove or Opt.PackFileToReplace):
 | |
|         Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE)
 | |
| 
 | |
|     if Opt.CustomPath and Opt.UseGuidedPkgPath:
 | |
|         Logger.Warn("UPT", ST.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH)
 | |
|         Opt.UseGuidedPkgPath = False
 | |
| 
 | |
| ## SetLogLevel
 | |
| #
 | |
| def SetLogLevel(Opt):
 | |
|     if Opt.opt_verbose:
 | |
|         Logger.SetLevel(Logger.VERBOSE)
 | |
|     elif Opt.opt_quiet:
 | |
|         Logger.SetLevel(Logger.QUIET + 1)
 | |
|     elif Opt.debug_level != None:
 | |
|         if Opt.debug_level < 0 or Opt.debug_level > 9:
 | |
|             Logger.Warn("UPT", ST.ERR_DEBUG_LEVEL)
 | |
|             Logger.SetLevel(Logger.INFO)
 | |
|         else:
 | |
|             Logger.SetLevel(Opt.debug_level + 1)
 | |
|     elif Opt.opt_slient:
 | |
|         Logger.SetLevel(Logger.SILENT)
 | |
|     else:
 | |
|         Logger.SetLevel(Logger.INFO)
 | |
| 
 | |
| ## Main
 | |
| #
 | |
| # Main
 | |
| #
 | |
| def Main():
 | |
|     Logger.Initialize()
 | |
| 
 | |
|     Parser = OptionParser(version=(MSG_VERSION + ' Build ' + gBUILD_VERSION), description=MSG_DESCRIPTION,
 | |
|                           prog="UPT.exe", usage=MSG_USAGE)
 | |
| 
 | |
|     Parser.add_option("-d", "--debug", action="store", type="int", dest="debug_level", help=ST.HLP_PRINT_DEBUG_INFO)
 | |
| 
 | |
|     Parser.add_option("-v", "--verbose", action="store_true", dest="opt_verbose",
 | |
|                       help=ST.HLP_PRINT_INFORMATIONAL_STATEMENT)
 | |
| 
 | |
|     Parser.add_option("-s", "--silent", action="store_true", dest="opt_slient", help=ST.HLP_RETURN_NO_DISPLAY)
 | |
| 
 | |
|     Parser.add_option("-q", "--quiet", action="store_true", dest="opt_quiet", help=ST.HLP_RETURN_AND_DISPLAY)
 | |
| 
 | |
|     Parser.add_option("-i", "--install", action="store", type="string", dest="Install_Distribution_Package_File",
 | |
|                       help=ST.HLP_SPECIFY_PACKAGE_NAME_INSTALL)
 | |
| 
 | |
|     Parser.add_option("-c", "--create", action="store", type="string", dest="Create_Distribution_Package_File",
 | |
|                       help=ST.HLP_SPECIFY_PACKAGE_NAME_CREATE)
 | |
| 
 | |
|     Parser.add_option("-r", "--remove", action="store", type="string", dest="Remove_Distribution_Package_File",
 | |
|                       help=ST.HLP_SPECIFY_PACKAGE_NAME_REMOVE)
 | |
| 
 | |
|     Parser.add_option("-t", "--template", action="store", type="string", dest="Package_Information_Data_File",
 | |
|                       help=ST.HLP_SPECIFY_TEMPLATE_NAME_CREATE)
 | |
| 
 | |
|     Parser.add_option("-p", "--dec-filename", action="append", type="string", dest="EDK2_DEC_Filename",
 | |
|                       help=ST.HLP_SPECIFY_DEC_NAME_CREATE)
 | |
| 
 | |
|     Parser.add_option("-m", "--inf-filename", action="append", type="string", dest="EDK2_INF_Filename",
 | |
|                       help=ST.HLP_SPECIFY_INF_NAME_CREATE)
 | |
| 
 | |
|     Parser.add_option("-l", "--list", action="store_true", dest="List_Dist_Installed",
 | |
|                       help=ST.HLP_LIST_DIST_INSTALLED)
 | |
| 
 | |
|     Parser.add_option("-f", "--force", action="store_true", dest="Yes", help=ST.HLP_DISABLE_PROMPT)
 | |
| 
 | |
|     Parser.add_option("-n", "--custom-path", action="store_true", dest="CustomPath", help=ST.HLP_CUSTOM_PATH_PROMPT)
 | |
| 
 | |
|     Parser.add_option("-x", "--free-lock", action="store_true", dest="SkipLock", help=ST.HLP_SKIP_LOCK_CHECK)
 | |
| 
 | |
|     Parser.add_option("-u", "--replace", action="store", type="string", dest="Replace_Distribution_Package_File",
 | |
|                       help=ST.HLP_SPECIFY_PACKAGE_NAME_REPLACE)
 | |
| 
 | |
|     Parser.add_option("-o", "--original", action="store", type="string", dest="Original_Distribution_Package_File",
 | |
|                       help=ST.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED)
 | |
| 
 | |
|     Parser.add_option("--use-guided-paths", action="store_true", dest="Use_Guided_Paths", help=ST.HLP_USE_GUIDED_PATHS)
 | |
| 
 | |
|     Parser.add_option("-j", "--test-install", action="append", type="string",
 | |
|                       dest="Test_Install_Distribution_Package_Files", help=ST.HLP_TEST_INSTALL)
 | |
| 
 | |
|     Opt = Parser.parse_args()[0]
 | |
| 
 | |
|     Var2Var = [
 | |
|         ("PackageInformationDataFile", Opt.Package_Information_Data_File),
 | |
|         ("PackFileToInstall", Opt.Install_Distribution_Package_File),
 | |
|         ("PackFileToCreate", Opt.Create_Distribution_Package_File),
 | |
|         ("PackFileToRemove", Opt.Remove_Distribution_Package_File),
 | |
|         ("PackageFileList", Opt.EDK2_DEC_Filename),
 | |
|         ("ModuleFileList", Opt.EDK2_INF_Filename),
 | |
|         ("InventoryWs", Opt.List_Dist_Installed),
 | |
|         ("PackFileToReplace", Opt.Replace_Distribution_Package_File),
 | |
|         ("PackFileToBeReplaced", Opt.Original_Distribution_Package_File),
 | |
|         ("UseGuidedPkgPath", Opt.Use_Guided_Paths),
 | |
|         ("TestDistFiles", Opt.Test_Install_Distribution_Package_Files)
 | |
|     ]
 | |
| 
 | |
|     for Var in Var2Var:
 | |
|         setattr(Opt, Var[0], Var[1])
 | |
| 
 | |
|     try:
 | |
|         GlobalData.gWORKSPACE, GlobalData.gPACKAGE_PATH = GetWorkspace()
 | |
|     except FatalError, XExcept:
 | |
|         if Logger.GetLevel() <= Logger.DEBUG_9:
 | |
|             Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())
 | |
|         return XExcept.args[0]
 | |
| 
 | |
|     # Start *********************************************
 | |
|     # Support WORKSPACE is a long path
 | |
|     # Only work well on windows
 | |
|     # Linux Solution TBD
 | |
|     if pf.system() == 'Windows':
 | |
|         os.system('@echo off\nsubst b: /D')
 | |
|         os.system('subst b: "%s"' % GlobalData.gWORKSPACE)
 | |
|         GlobalData.gWORKSPACE = 'B:\\'
 | |
|     # End ***********************************************
 | |
| 
 | |
|     WorkspaceDir = GlobalData.gWORKSPACE
 | |
| 
 | |
|     SetLogLevel(Opt)
 | |
| 
 | |
|     Mgr = FileHook.RecoverMgr(WorkspaceDir)
 | |
|     FileHook.SetRecoverMgr(Mgr)
 | |
| 
 | |
|     GlobalData.gDB = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, \
 | |
|                                                                "Conf/DistributionPackageDatabase.db")), WorkspaceDir)
 | |
|     GlobalData.gDB.InitDatabase(Opt.SkipLock)
 | |
| 
 | |
|     #
 | |
|     # Make sure the Db will get closed correctly
 | |
|     #
 | |
|     try:
 | |
|         ReturnCode = 0
 | |
|         CheckConflictOption(Opt)
 | |
| 
 | |
|         RunModule = None
 | |
|         if Opt.PackFileToCreate:
 | |
|             if Opt.PackageInformationDataFile:
 | |
|                 if not os.path.exists(Opt.PackageInformationDataFile):
 | |
|                     if not os.path.exists(os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)):
 | |
|                         Logger.Error("\nUPT", FILE_NOT_FOUND, ST.ERR_NO_TEMPLATE_FILE % Opt.PackageInformationDataFile)
 | |
|                     else:
 | |
|                         Opt.PackageInformationDataFile = os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)
 | |
|             else:
 | |
|                 Logger.Error("UPT", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_T_OPTION)
 | |
|             if not Opt.PackFileToCreate.endswith('.dist'):
 | |
|                 Logger.Error("CreatePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToCreate)
 | |
|             RunModule = MkPkg.Main
 | |
| 
 | |
|         elif Opt.PackFileToInstall:
 | |
|             if not Opt.PackFileToInstall.endswith('.dist'):
 | |
|                 Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToInstall)
 | |
| 
 | |
|             AbsPath = GetFullPathDist(Opt.PackFileToInstall, WorkspaceDir)
 | |
|             if not AbsPath:
 | |
|                 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Opt.PackFileToInstall)
 | |
| 
 | |
|             Opt.PackFileToInstall = AbsPath
 | |
|             setattr(Opt, 'PackageFile', Opt.PackFileToInstall)
 | |
|             RunModule = InstallPkg.Main
 | |
| 
 | |
|         elif Opt.PackFileToRemove:
 | |
|             if not Opt.PackFileToRemove.endswith('.dist'):
 | |
|                 Logger.Error("RemovePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToRemove)
 | |
|             head, tail = os.path.split(Opt.PackFileToRemove)
 | |
|             if head or not tail:
 | |
|                 Logger.Error("RemovePkg",
 | |
|                              FILE_TYPE_MISMATCH,
 | |
|                              ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REMOVE % Opt.PackFileToRemove)
 | |
| 
 | |
|             setattr(Opt, 'DistributionFile', Opt.PackFileToRemove)
 | |
|             RunModule = RmPkg.Main
 | |
|         elif Opt.InventoryWs:
 | |
|             RunModule = InventoryWs.Main
 | |
| 
 | |
|         elif Opt.PackFileToBeReplaced and not Opt.PackFileToReplace:
 | |
|             Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_U_OPTION)
 | |
| 
 | |
|         elif Opt.PackFileToReplace:
 | |
|             if not Opt.PackFileToReplace.endswith('.dist'):
 | |
|                 Logger.Error("ReplacePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToReplace)
 | |
|             if not Opt.PackFileToBeReplaced:
 | |
|                 Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_O_OPTION)
 | |
|             if not Opt.PackFileToBeReplaced.endswith('.dist'):
 | |
|                 Logger.Error("ReplacePkg",
 | |
|                              FILE_TYPE_MISMATCH,
 | |
|                              ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToBeReplaced)
 | |
| 
 | |
|             head, tail = os.path.split(Opt.PackFileToBeReplaced)
 | |
|             if head or not tail:
 | |
|                 Logger.Error("ReplacePkg",
 | |
|                              FILE_TYPE_MISMATCH,
 | |
|                              ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG % Opt.PackFileToBeReplaced)
 | |
| 
 | |
|             AbsPath = GetFullPathDist(Opt.PackFileToReplace, WorkspaceDir)
 | |
|             if not AbsPath:
 | |
|                 Logger.Error("ReplacePkg", FILE_NOT_FOUND, ST.ERR_REPLACE_DIST_NOT_FOUND % Opt.PackFileToReplace)
 | |
| 
 | |
|             Opt.PackFileToReplace = AbsPath
 | |
|             RunModule = ReplacePkg.Main
 | |
| 
 | |
|         elif Opt.Test_Install_Distribution_Package_Files:
 | |
|             for Dist in Opt.Test_Install_Distribution_Package_Files:
 | |
|                 if not Dist.endswith('.dist'):
 | |
|                     Logger.Error("TestInstall", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Dist)
 | |
| 
 | |
|             setattr(Opt, 'DistFiles', Opt.Test_Install_Distribution_Package_Files)
 | |
|             RunModule = TestInstall.Main
 | |
| 
 | |
|         else:
 | |
|             Parser.print_usage()
 | |
|             return OPTION_MISSING
 | |
| 
 | |
|         ReturnCode = RunModule(Opt)
 | |
|     except FatalError, XExcept:
 | |
|         ReturnCode = XExcept.args[0]
 | |
|         if Logger.GetLevel() <= Logger.DEBUG_9:
 | |
|             Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
 | |
|                          format_exc())
 | |
|     finally:
 | |
|         try:
 | |
|             if ReturnCode != 0 and ReturnCode != UPT_ALREADY_INSTALLED_ERROR:
 | |
|                 Logger.Quiet(ST.MSG_RECOVER_START)
 | |
|                 GlobalData.gDB.RollBack()
 | |
|                 Mgr.rollback()
 | |
|                 Logger.Quiet(ST.MSG_RECOVER_DONE)
 | |
|             else:
 | |
|                 GlobalData.gDB.Commit()
 | |
|                 Mgr.commit()
 | |
|         except StandardError:
 | |
|             Logger.Quiet(ST.MSG_RECOVER_FAIL)
 | |
|         GlobalData.gDB.CloseDb()
 | |
|         if pf.system() == 'Windows':
 | |
|             os.system('subst b: /D')
 | |
| 
 | |
|     return ReturnCode
 | |
| 
 | |
| ## GetFullPathDist
 | |
| #
 | |
| #  This function will check DistFile existence, if not absolute path, then try current working directory,
 | |
| #  then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None
 | |
| #
 | |
| # @param DistFile:       The distribution file in either relative path or absolute path
 | |
| # @param WorkspaceDir:   Workspace Directory
 | |
| # @return AbsPath:       The Absolute path of the distribution file if existed, None else
 | |
| #
 | |
| def GetFullPathDist(DistFile, WorkspaceDir):
 | |
|     if os.path.isabs(DistFile):
 | |
|         if not (os.path.exists(DistFile) and os.path.isfile(DistFile)):
 | |
|             return None
 | |
|         else:
 | |
|             return DistFile
 | |
|     else:
 | |
|         AbsPath = os.path.normpath(os.path.join(os.getcwd(), DistFile))
 | |
|         if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)):
 | |
|             AbsPath = os.path.normpath(os.path.join(WorkspaceDir, DistFile))
 | |
|             if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)):
 | |
|                 return None
 | |
| 
 | |
|         return AbsPath
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     RETVAL = Main()
 | |
|     #
 | |
|     # 0-127 is a safe return range, and 1 is a standard default error
 | |
|     #
 | |
|     if RETVAL < 0 or RETVAL > 127:
 | |
|         RETVAL = 1
 | |
|     sys.exit(RETVAL)
 |