## @file | |
# | |
# This file is the main entry for UPT | |
# | |
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> | |
# | |
# SPDX-License-Identifier: BSD-2-Clause-Patent | |
# | |
''' | |
UPT | |
''' | |
## import modules | |
# | |
import locale | |
import sys | |
from imp import reload | |
encoding = locale.getdefaultlocale()[1] | |
if encoding: | |
reload(sys) | |
sys.setdefaultencoding(encoding) | |
from Core import FileHook | |
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 is not 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="append", 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 as XExcept: | |
if Logger.GetLevel() <= Logger.DEBUG_9: | |
Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc()) | |
return XExcept.args[0] | |
# Support WORKSPACE is a long path | |
# Only works for windows system | |
if pf.system() == 'Windows': | |
Vol = 'B:' | |
for Index in range(90, 65, -1): | |
Vol = chr(Index) + ':' | |
if not os.path.isdir(Vol): | |
os.system('subst %s "%s"' % (Vol, GlobalData.gWORKSPACE)) | |
break | |
GlobalData.gWORKSPACE = '%s\\' % Vol | |
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: | |
AbsPath = [] | |
for Item in Opt.PackFileToInstall: | |
if not Item.endswith('.dist'): | |
Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Item) | |
AbsPath.append(GetFullPathDist(Item, WorkspaceDir)) | |
if not AbsPath: | |
Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Item) | |
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 as 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 Exception: | |
Logger.Quiet(ST.MSG_RECOVER_FAIL) | |
GlobalData.gDB.CloseDb() | |
if pf.system() == 'Windows': | |
os.system('subst %s /D' % GlobalData.gWORKSPACE.replace('\\', '')) | |
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) |