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