BaseTools: Remove the deprecated hash_key()
[mirror_edk2.git] / BaseTools / Source / Python / UPT / UPT.py
1 ## @file
2 #
3 # This file is the main entry for UPT
4 #
5 # Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
6 #
7 # This program and the accompanying materials are licensed and made available
8 # under the terms and conditions of the BSD License which accompanies this
9 # distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
11 #
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #
15
16 '''
17 UPT
18 '''
19
20 ## import modules
21 #
22 import locale
23 import sys
24 encoding = locale.getdefaultlocale()[1]
25 if encoding:
26 reload(sys)
27 sys.setdefaultencoding(encoding)
28 from Core import FileHook
29 import os.path
30 from sys import platform
31 import platform as pf
32 from optparse import OptionParser
33 from traceback import format_exc
34 from platform import python_version
35
36 from Logger import StringTable as ST
37 import Logger.Log as Logger
38 from Logger.StringTable import MSG_VERSION
39 from Logger.StringTable import MSG_DESCRIPTION
40 from Logger.StringTable import MSG_USAGE
41 from Logger.ToolError import FILE_NOT_FOUND
42 from Logger.ToolError import OPTION_MISSING
43 from Logger.ToolError import FILE_TYPE_MISMATCH
44 from Logger.ToolError import OPTION_CONFLICT
45 from Logger.ToolError import FatalError
46 from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR
47 from Common.MultipleWorkspace import MultipleWorkspace as mws
48
49 import MkPkg
50 import InstallPkg
51 import RmPkg
52 import InventoryWs
53 import ReplacePkg
54 import TestInstall
55 from Library.Misc import GetWorkspace
56 from Library import GlobalData
57 from Core.IpiDb import IpiDatabase
58 from BuildVersion import gBUILD_VERSION
59
60 ## CheckConflictOption
61 #
62 # CheckConflictOption
63 #
64 def CheckConflictOption(Opt):
65 if (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove or Opt.PackFileToReplace) \
66 and Opt.InventoryWs:
67 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_L_OA_EXCLUSIVE)
68 elif Opt.PackFileToReplace and (Opt.PackFileToCreate or Opt.PackFileToInstall or Opt.PackFileToRemove):
69 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_U_ICR_EXCLUSIVE)
70 elif (Opt.PackFileToCreate and Opt.PackFileToInstall and Opt.PackFileToRemove):
71 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_REQUIRE_I_C_R_OPTION)
72 elif Opt.PackFileToCreate and Opt.PackFileToInstall:
73 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_C_EXCLUSIVE)
74 elif Opt.PackFileToInstall and Opt.PackFileToRemove:
75 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_I_R_EXCLUSIVE)
76 elif Opt.PackFileToCreate and Opt.PackFileToRemove:
77 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE)
78 elif Opt.TestDistFiles and (Opt.PackFileToCreate or Opt.PackFileToInstall \
79 or Opt.PackFileToRemove or Opt.PackFileToReplace):
80 Logger.Error("UPT", OPTION_CONFLICT, ExtraData=ST.ERR_C_R_EXCLUSIVE)
81
82 if Opt.CustomPath and Opt.UseGuidedPkgPath:
83 Logger.Warn("UPT", ST.WARN_CUSTOMPATH_OVERRIDE_USEGUIDEDPATH)
84 Opt.UseGuidedPkgPath = False
85
86 ## SetLogLevel
87 #
88 def SetLogLevel(Opt):
89 if Opt.opt_verbose:
90 Logger.SetLevel(Logger.VERBOSE)
91 elif Opt.opt_quiet:
92 Logger.SetLevel(Logger.QUIET + 1)
93 elif Opt.debug_level is not None:
94 if Opt.debug_level < 0 or Opt.debug_level > 9:
95 Logger.Warn("UPT", ST.ERR_DEBUG_LEVEL)
96 Logger.SetLevel(Logger.INFO)
97 else:
98 Logger.SetLevel(Opt.debug_level + 1)
99 elif Opt.opt_slient:
100 Logger.SetLevel(Logger.SILENT)
101 else:
102 Logger.SetLevel(Logger.INFO)
103
104 ## Main
105 #
106 # Main
107 #
108 def Main():
109 Logger.Initialize()
110
111 Parser = OptionParser(version=(MSG_VERSION + ' Build ' + gBUILD_VERSION), description=MSG_DESCRIPTION,
112 prog="UPT.exe", usage=MSG_USAGE)
113
114 Parser.add_option("-d", "--debug", action="store", type="int", dest="debug_level", help=ST.HLP_PRINT_DEBUG_INFO)
115
116 Parser.add_option("-v", "--verbose", action="store_true", dest="opt_verbose",
117 help=ST.HLP_PRINT_INFORMATIONAL_STATEMENT)
118
119 Parser.add_option("-s", "--silent", action="store_true", dest="opt_slient", help=ST.HLP_RETURN_NO_DISPLAY)
120
121 Parser.add_option("-q", "--quiet", action="store_true", dest="opt_quiet", help=ST.HLP_RETURN_AND_DISPLAY)
122
123 Parser.add_option("-i", "--install", action="append", type="string", dest="Install_Distribution_Package_File",
124 help=ST.HLP_SPECIFY_PACKAGE_NAME_INSTALL)
125
126 Parser.add_option("-c", "--create", action="store", type="string", dest="Create_Distribution_Package_File",
127 help=ST.HLP_SPECIFY_PACKAGE_NAME_CREATE)
128
129 Parser.add_option("-r", "--remove", action="store", type="string", dest="Remove_Distribution_Package_File",
130 help=ST.HLP_SPECIFY_PACKAGE_NAME_REMOVE)
131
132 Parser.add_option("-t", "--template", action="store", type="string", dest="Package_Information_Data_File",
133 help=ST.HLP_SPECIFY_TEMPLATE_NAME_CREATE)
134
135 Parser.add_option("-p", "--dec-filename", action="append", type="string", dest="EDK2_DEC_Filename",
136 help=ST.HLP_SPECIFY_DEC_NAME_CREATE)
137
138 Parser.add_option("-m", "--inf-filename", action="append", type="string", dest="EDK2_INF_Filename",
139 help=ST.HLP_SPECIFY_INF_NAME_CREATE)
140
141 Parser.add_option("-l", "--list", action="store_true", dest="List_Dist_Installed",
142 help=ST.HLP_LIST_DIST_INSTALLED)
143
144 Parser.add_option("-f", "--force", action="store_true", dest="Yes", help=ST.HLP_DISABLE_PROMPT)
145
146 Parser.add_option("-n", "--custom-path", action="store_true", dest="CustomPath", help=ST.HLP_CUSTOM_PATH_PROMPT)
147
148 Parser.add_option("-x", "--free-lock", action="store_true", dest="SkipLock", help=ST.HLP_SKIP_LOCK_CHECK)
149
150 Parser.add_option("-u", "--replace", action="store", type="string", dest="Replace_Distribution_Package_File",
151 help=ST.HLP_SPECIFY_PACKAGE_NAME_REPLACE)
152
153 Parser.add_option("-o", "--original", action="store", type="string", dest="Original_Distribution_Package_File",
154 help=ST.HLP_SPECIFY_PACKAGE_NAME_TO_BE_REPLACED)
155
156 Parser.add_option("--use-guided-paths", action="store_true", dest="Use_Guided_Paths", help=ST.HLP_USE_GUIDED_PATHS)
157
158 Parser.add_option("-j", "--test-install", action="append", type="string",
159 dest="Test_Install_Distribution_Package_Files", help=ST.HLP_TEST_INSTALL)
160
161 Opt = Parser.parse_args()[0]
162
163 Var2Var = [
164 ("PackageInformationDataFile", Opt.Package_Information_Data_File),
165 ("PackFileToInstall", Opt.Install_Distribution_Package_File),
166 ("PackFileToCreate", Opt.Create_Distribution_Package_File),
167 ("PackFileToRemove", Opt.Remove_Distribution_Package_File),
168 ("PackageFileList", Opt.EDK2_DEC_Filename),
169 ("ModuleFileList", Opt.EDK2_INF_Filename),
170 ("InventoryWs", Opt.List_Dist_Installed),
171 ("PackFileToReplace", Opt.Replace_Distribution_Package_File),
172 ("PackFileToBeReplaced", Opt.Original_Distribution_Package_File),
173 ("UseGuidedPkgPath", Opt.Use_Guided_Paths),
174 ("TestDistFiles", Opt.Test_Install_Distribution_Package_Files)
175 ]
176
177 for Var in Var2Var:
178 setattr(Opt, Var[0], Var[1])
179
180 try:
181 GlobalData.gWORKSPACE, GlobalData.gPACKAGE_PATH = GetWorkspace()
182 except FatalError as XExcept:
183 if Logger.GetLevel() <= Logger.DEBUG_9:
184 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())
185 return XExcept.args[0]
186
187 # Support WORKSPACE is a long path
188 # Only works for windows system
189 if pf.system() == 'Windows':
190 Vol = 'B:'
191 for Index in range(90, 65, -1):
192 Vol = chr(Index) + ':'
193 if not os.path.isdir(Vol):
194 os.system('subst %s "%s"' % (Vol, GlobalData.gWORKSPACE))
195 break
196 GlobalData.gWORKSPACE = '%s\\' % Vol
197
198 WorkspaceDir = GlobalData.gWORKSPACE
199
200 SetLogLevel(Opt)
201
202 Mgr = FileHook.RecoverMgr(WorkspaceDir)
203 FileHook.SetRecoverMgr(Mgr)
204
205 GlobalData.gDB = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, \
206 "Conf/DistributionPackageDatabase.db")), WorkspaceDir)
207 GlobalData.gDB.InitDatabase(Opt.SkipLock)
208
209 #
210 # Make sure the Db will get closed correctly
211 #
212 try:
213 ReturnCode = 0
214 CheckConflictOption(Opt)
215
216 RunModule = None
217 if Opt.PackFileToCreate:
218 if Opt.PackageInformationDataFile:
219 if not os.path.exists(Opt.PackageInformationDataFile):
220 if not os.path.exists(os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)):
221 Logger.Error("\nUPT", FILE_NOT_FOUND, ST.ERR_NO_TEMPLATE_FILE % Opt.PackageInformationDataFile)
222 else:
223 Opt.PackageInformationDataFile = os.path.join(WorkspaceDir, Opt.PackageInformationDataFile)
224 else:
225 Logger.Error("UPT", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_T_OPTION)
226 if not Opt.PackFileToCreate.endswith('.dist'):
227 Logger.Error("CreatePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToCreate)
228 RunModule = MkPkg.Main
229
230 elif Opt.PackFileToInstall:
231 AbsPath = []
232 for Item in Opt.PackFileToInstall:
233 if not Item.endswith('.dist'):
234 Logger.Error("InstallPkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Item)
235
236 AbsPath.append(GetFullPathDist(Item, WorkspaceDir))
237 if not AbsPath:
238 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_INSTALL_DIST_NOT_FOUND % Item)
239
240 Opt.PackFileToInstall = AbsPath
241 setattr(Opt, 'PackageFile', Opt.PackFileToInstall)
242 RunModule = InstallPkg.Main
243
244 elif Opt.PackFileToRemove:
245 if not Opt.PackFileToRemove.endswith('.dist'):
246 Logger.Error("RemovePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToRemove)
247 head, tail = os.path.split(Opt.PackFileToRemove)
248 if head or not tail:
249 Logger.Error("RemovePkg",
250 FILE_TYPE_MISMATCH,
251 ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REMOVE % Opt.PackFileToRemove)
252
253 setattr(Opt, 'DistributionFile', Opt.PackFileToRemove)
254 RunModule = RmPkg.Main
255 elif Opt.InventoryWs:
256 RunModule = InventoryWs.Main
257
258 elif Opt.PackFileToBeReplaced and not Opt.PackFileToReplace:
259 Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_U_OPTION)
260
261 elif Opt.PackFileToReplace:
262 if not Opt.PackFileToReplace.endswith('.dist'):
263 Logger.Error("ReplacePkg", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToReplace)
264 if not Opt.PackFileToBeReplaced:
265 Logger.Error("ReplacePkg", OPTION_MISSING, ExtraData=ST.ERR_REQUIRE_O_OPTION)
266 if not Opt.PackFileToBeReplaced.endswith('.dist'):
267 Logger.Error("ReplacePkg",
268 FILE_TYPE_MISMATCH,
269 ExtraData=ST.ERR_DIST_EXT_ERROR % Opt.PackFileToBeReplaced)
270
271 head, tail = os.path.split(Opt.PackFileToBeReplaced)
272 if head or not tail:
273 Logger.Error("ReplacePkg",
274 FILE_TYPE_MISMATCH,
275 ExtraData=ST.ERR_DIST_FILENAME_ONLY_FOR_REPLACE_ORIG % Opt.PackFileToBeReplaced)
276
277 AbsPath = GetFullPathDist(Opt.PackFileToReplace, WorkspaceDir)
278 if not AbsPath:
279 Logger.Error("ReplacePkg", FILE_NOT_FOUND, ST.ERR_REPLACE_DIST_NOT_FOUND % Opt.PackFileToReplace)
280
281 Opt.PackFileToReplace = AbsPath
282 RunModule = ReplacePkg.Main
283
284 elif Opt.Test_Install_Distribution_Package_Files:
285 for Dist in Opt.Test_Install_Distribution_Package_Files:
286 if not Dist.endswith('.dist'):
287 Logger.Error("TestInstall", FILE_TYPE_MISMATCH, ExtraData=ST.ERR_DIST_EXT_ERROR % Dist)
288
289 setattr(Opt, 'DistFiles', Opt.Test_Install_Distribution_Package_Files)
290 RunModule = TestInstall.Main
291
292 else:
293 Parser.print_usage()
294 return OPTION_MISSING
295
296 ReturnCode = RunModule(Opt)
297 except FatalError as XExcept:
298 ReturnCode = XExcept.args[0]
299 if Logger.GetLevel() <= Logger.DEBUG_9:
300 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
301 format_exc())
302 finally:
303 try:
304 if ReturnCode != 0 and ReturnCode != UPT_ALREADY_INSTALLED_ERROR:
305 Logger.Quiet(ST.MSG_RECOVER_START)
306 GlobalData.gDB.RollBack()
307 Mgr.rollback()
308 Logger.Quiet(ST.MSG_RECOVER_DONE)
309 else:
310 GlobalData.gDB.Commit()
311 Mgr.commit()
312 except StandardError:
313 Logger.Quiet(ST.MSG_RECOVER_FAIL)
314 GlobalData.gDB.CloseDb()
315
316 if pf.system() == 'Windows':
317 os.system('subst %s /D' % GlobalData.gWORKSPACE.replace('\\',''))
318
319 return ReturnCode
320
321 ## GetFullPathDist
322 #
323 # This function will check DistFile existence, if not absolute path, then try current working directory,
324 # then $(WORKSPACE),and return the AbsPath. If file doesn't find, then return None
325 #
326 # @param DistFile: The distribution file in either relative path or absolute path
327 # @param WorkspaceDir: Workspace Directory
328 # @return AbsPath: The Absolute path of the distribution file if existed, None else
329 #
330 def GetFullPathDist(DistFile, WorkspaceDir):
331 if os.path.isabs(DistFile):
332 if not (os.path.exists(DistFile) and os.path.isfile(DistFile)):
333 return None
334 else:
335 return DistFile
336 else:
337 AbsPath = os.path.normpath(os.path.join(os.getcwd(), DistFile))
338 if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)):
339 AbsPath = os.path.normpath(os.path.join(WorkspaceDir, DistFile))
340 if not (os.path.exists(AbsPath) and os.path.isfile(AbsPath)):
341 return None
342
343 return AbsPath
344
345 if __name__ == '__main__':
346 RETVAL = Main()
347 #
348 # 0-127 is a safe return range, and 1 is a standard default error
349 #
350 if RETVAL < 0 or RETVAL > 127:
351 RETVAL = 1
352 sys.exit(RETVAL)