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