]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/PackagingTool/InstallPkg.py
Sync EDKII BaseTools to BaseTools project r1903.
[mirror_edk2.git] / BaseTools / Source / Python / PackagingTool / InstallPkg.py
CommitLineData
30fdf114
LG
1## @file\r
2# Install distribution package.\r
3#\r
4# Copyright (c) 2007, Intel Corporation\r
5# All rights reserved. This program and the accompanying materials\r
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13\r
14##\r
15# Import Modules\r
16#\r
17import os\r
18import sys\r
19import glob\r
20import shutil\r
21import traceback\r
22import platform\r
23from optparse import OptionParser\r
24\r
25import Common.EdkLogger as EdkLogger\r
26from Common.BuildToolError import *\r
27from Common.Misc import *\r
28from Common.XmlParser import *\r
29from Common.InfClassObjectLight import Inf\r
30from Common.DecClassObjectLight import Dec\r
31\r
32from PackageFile import *\r
33from IpiDb import *\r
34from DependencyRules import *\r
35import md5\r
36\r
37# Version and Copyright\r
38VersionNumber = "0.1"\r
39__version__ = "%prog Version " + VersionNumber\r
40__copyright__ = "Copyright (c) 2008, Intel Corporation All rights reserved."\r
41\r
42## Check environment variables\r
43#\r
44# Check environment variables that must be set for build. Currently they are\r
45#\r
46# WORKSPACE The directory all packages/platforms start from\r
47# EDK_TOOLS_PATH The directory contains all tools needed by the build\r
48# PATH $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH\r
49#\r
50# If any of above environment variable is not set or has error, the build\r
51# will be broken.\r
52#\r
53def CheckEnvVariable():\r
54 # check WORKSPACE\r
55 if "WORKSPACE" not in os.environ:\r
56 EdkLogger.error("InstallPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",\r
57 ExtraData="WORKSPACE")\r
58\r
59 WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"])\r
60 if not os.path.exists(WorkspaceDir):\r
61 EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir)\r
62 elif ' ' in WorkspaceDir:\r
63 EdkLogger.error("InstallPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", \r
64 ExtraData=WorkspaceDir)\r
65 os.environ["WORKSPACE"] = WorkspaceDir\r
66\r
67## Parse command line options\r
68#\r
69# Using standard Python module optparse to parse command line option of this tool.\r
70#\r
71# @retval Opt A optparse.Values object containing the parsed options\r
72# @retval Args Target of build command\r
73#\r
74def MyOptionParser():\r
75 UsageString = "%prog -i <distribution_package> [-t] [-f] [-q | -v] [-h]"\r
76\r
77 Parser = OptionParser(description=__copyright__,version=__version__,prog="InstallPkg",usage=UsageString)\r
78\r
79 Parser.add_option("-?", action="help", help="show this help message and exit")\r
80\r
81 Parser.add_option("-i", "--distribution-package", action="store", type="string", dest="PackageFile",\r
82 help="The distribution package to be installed")\r
83\r
84 Parser.add_option("-t", "--install-tools", action="store_true", type=None, dest="Tools",\r
85 help="Specify it to install tools or ignore the tools of the distribution package.")\r
86 \r
87 Parser.add_option("-f", "--misc-files", action="store_true", type=None, dest="MiscFiles",\r
88 help="Specify it to install misc file or ignore the misc files of the distribution package.")\r
89\r
90 Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET,\r
91 help="Disable all messages except FATAL ERRORS.")\r
92\r
93 Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE,\r
94 help="Turn on verbose output")\r
95\r
96 Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel",\r
97 help="Enable debug messages at specified level.")\r
98\r
99 Parser.set_defaults(LogLevel=EdkLogger.INFO)\r
100\r
101 (Opt, Args)=Parser.parse_args()\r
102\r
103 return Opt\r
104\r
105def InstallNewPackage(WorkspaceDir, Path):\r
106 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path))\r
107 if os.path.exists(FullPath):\r
108 print "Directory [%s] already exists, please select another location, press [Enter] with no input to quit:" %Path\r
109 Input = sys.stdin.readline()\r
110 Input = Input.replace('\r', '').replace('\n', '')\r
111 if Input == '':\r
112 EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "User interrupt")\r
113 Input = Input.replace('\r', '').replace('\n', '')\r
114 return InstallNewPackage(WorkspaceDir, Input)\r
115 else:\r
116 return Path\r
117\r
118def InstallNewFile(WorkspaceDir, File):\r
119 FullPath = os.path.normpath(os.path.join(WorkspaceDir, File))\r
120 if os.path.exists(FullPath):\r
121 print "File [%s] already exists, please select another path, press [Enter] with no input to quit:" %File\r
122 Input = sys.stdin.readline()\r
123 Input = Input.replace('\r', '').replace('\n', '')\r
124 if Input == '':\r
125 EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "User interrupt")\r
126 Input = Input.replace('\r', '').replace('\n', '')\r
127 return InstallNewFile(WorkspaceDir, Input)\r
128 else:\r
129 return File\r
130\r
131## Tool entrance method\r
132#\r
133# This method mainly dispatch specific methods per the command line options.\r
134# If no error found, return zero value so the caller of this tool can know\r
135# if it's executed successfully or not.\r
136#\r
137# @retval 0 Tool was successful\r
138# @retval 1 Tool failed\r
139#\r
140def Main():\r
141 EdkLogger.Initialize()\r
142 Options = None\r
143 DistFileName = 'dist.pkg'\r
144 ContentFileName = 'content.zip'\r
145 DistFile, ContentZipFile, UnpackDir = None, None, None\r
146 \r
147 Options = MyOptionParser()\r
148 try:\r
149 if Options.LogLevel < EdkLogger.DEBUG_9:\r
150 EdkLogger.SetLevel(Options.LogLevel + 1)\r
151 else:\r
152 EdkLogger.SetLevel(Options.LogLevel)\r
153\r
154 CheckEnvVariable()\r
155 WorkspaceDir = os.environ["WORKSPACE"]\r
156 if not Options.PackageFile:\r
157 EdkLogger.error("InstallPkg", OPTION_NOT_SUPPORTED, ExtraData="Must specify one distribution package")\r
158\r
159 # unzip dist.pkg file\r
160 EdkLogger.quiet("Unzipping and parsing distribution package XML file ... ")\r
161 DistFile = PackageFile(Options.PackageFile)\r
162 UnpackDir = os.path.normpath(os.path.join(WorkspaceDir, ".tmp"))\r
163 DistPkgFile = DistFile.UnpackFile(DistFileName, os.path.normpath(os.path.join(UnpackDir, DistFileName)))\r
164 if not DistPkgFile:\r
165 EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "File [%s] is broken in distribution package" %DistFileName)\r
166 \r
167 # Generate distpkg\r
168 DistPkgObj = DistributionPackageXml()\r
169 DistPkg = DistPkgObj.FromXml(DistPkgFile)\r
170\r
171 # prepare check dependency\r
172 Db = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, "Conf/DistributionPackageDatabase.db")))\r
173 Db.InitDatabase()\r
174 Dep = DependencyRules(Db)\r
175 \r
176 # Check distribution package exist\r
177 if Dep.CheckDpExists(DistPkg.Header.Guid, DistPkg.Header.Version):\r
178 EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "This distribution package has been installed", ExtraData=DistPkg.Header.Name)\r
179 \r
180 # unzip contents.zip file\r
181 ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(UnpackDir, ContentFileName)))\r
182 ContentZipFile = PackageFile(ContentFile)\r
183 if not ContentFile:\r
184 EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "File [%s] is broken in distribution package" %ContentFileName)\r
185 \r
186 # verify MD5 signature\r
187 Md5Sigature = md5.new(open(ContentFile).read())\r
188 if DistPkg.Header.Signature != Md5Sigature.hexdigest():\r
189 EdkLogger.error("InstallPkg", FILE_CHECKSUM_FAILURE, ExtraData=ContentFile)\r
190 \r
191 # Check package exist and install\r
192 for Guid,Version,Path in DistPkg.PackageSurfaceArea:\r
193 PackagePath = os.path.dirname(Path)\r
194 NewPackagePath = PackagePath\r
195 Package = DistPkg.PackageSurfaceArea[Guid,Version,Path]\r
196 EdkLogger.info("Installing package ... %s" % Package.PackageHeader.Name)\r
197 if Dep.CheckPackageExists(Guid, Version):\r
198 EdkLogger.quiet("Package [%s] has been installed" %Path)\r
199 NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath)\r
200 Package.FileList = []\r
201 for Item in Package.MiscFiles.Files:\r
202 FromFile = os.path.join(PackagePath, Item.Filename)\r
203 ToFile = os.path.normpath(os.path.join(WorkspaceDir, NewPackagePath, Item.Filename))\r
204 ContentZipFile.UnpackFile(FromFile, ToFile)\r
205 Package.FileList.append(ToFile)\r
206 \r
207 # Update package\r
208 Package.PackageHeader.CombinePath = Package.PackageHeader.CombinePath.replace(PackagePath, NewPackagePath, 1)\r
209 # Update modules of package\r
210 Module = None\r
211 for ModuleGuid, ModuleVersion, ModulePath in Package.Modules:\r
212 Module = Package.Modules[ModuleGuid, ModuleVersion, ModulePath]\r
213 NewModulePath = ModulePath.replace(PackagePath, NewPackagePath, 1)\r
214 del Package.Modules[ModuleGuid, ModuleVersion, ModulePath]\r
215 Package.Modules[ModuleGuid, ModuleVersion, NewModulePath] = Module\r
216 del DistPkg.PackageSurfaceArea[Guid,Version,Path]\r
217 DistPkg.PackageSurfaceArea[Guid,Version,Package.PackageHeader.CombinePath] = Package\r
218\r
219# SaveFileOnChange(os.path.join(Options.InstallDir, ModulePath, Module.Header.Name, ".inf"), Inf.ModuleToInf(Module), False)\r
220# EdkLogger.info("Installing package ... %s" % Package.Header.Name)\r
221# shutil.copytree(os.path.join(ContentFileDir, Path), Options.InstallDir)\r
222# SaveFileOnChange(os.path.join(Options.InstallDir, Path, Package.Header.Name, ".dec"), Dec.PackageToDec(Package), False)\r
223\r
224 # Check module exist and install\r
225 Module = None\r
226 for Guid,Version,Path in DistPkg.ModuleSurfaceArea:\r
227 ModulePath = os.path.dirname(Path)\r
228 NewModulePath = ModulePath\r
229 Module = DistPkg.ModuleSurfaceArea[Guid,Version,Path]\r
230 EdkLogger.info("Installing module ... %s" % Module.ModuleHeader.Name)\r
231 if Dep.CheckModuleExists(Guid, Version):\r
232 EdkLogger.quiet("Module [%s] has been installed" %Path)\r
233 NewModulePath = InstallNewPackage(WorkspaceDir, ModulePath)\r
234 Module.FileList = []\r
235 for Item in Module.MiscFiles.Files:\r
236 ModulePath = ModulePath[os.path.normpath(ModulePath).rfind(os.path.normpath('/'))+1:]\r
237 FromFile = os.path.join(ModulePath, Item.Filename)\r
238 ToFile = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath, Item.Filename))\r
239 ContentZipFile.UnpackFile(FromFile, ToFile)\r
240 Module.FileList.append(ToFile)\r
241 \r
242# EdkLogger.info("Installing module ... %s" % Module.Header.Name)\r
243# shutil.copytree(os.path.join(ContentFileDir, Path), Options.InstallDir)\r
244# SaveFileOnChange(os.path.join(Options.InstallDir, Path, Module.Header.Name, ".inf"), Inf.ModuleToInf(Module), False)\r
245 \r
246 # Update module\r
247 Module.ModuleHeader.CombinePath = Module.ModuleHeader.CombinePath.replace(os.path.dirname(Path), NewModulePath, 1)\r
248 del DistPkg.ModuleSurfaceArea[Guid,Version,Path]\r
249 DistPkg.ModuleSurfaceArea[Guid,Version,Module.ModuleHeader.CombinePath] = Module\r
250# \r
251# \r
252# for Guid,Version,Path in DistPkg.PackageSurfaceArea:\r
253# print Guid,Version,Path\r
254# for item in DistPkg.PackageSurfaceArea[Guid,Version,Path].FileList:\r
255# print item\r
256# for Guid,Version,Path in DistPkg.ModuleSurfaceArea:\r
257# print Guid,Version,Path\r
258# for item in DistPkg.ModuleSurfaceArea[Guid,Version,Path].FileList:\r
259# print item\r
260\r
261 if Options.Tools:\r
262 EdkLogger.info("Installing tools ... ")\r
263 for File in DistPkg.Tools.Files:\r
264 FromFile = File.Filename\r
265 ToFile = InstallNewFile(WorkspaceDir, FromFile)\r
266 ContentZipFile.UnpackFile(FromFile, ToFile)\r
267 if Options.MiscFiles:\r
268 EdkLogger.info("Installing misc files ... ")\r
269 for File in DistPkg.MiscellaneousFiles.Files:\r
270 FromFile = File.Filename\r
271 ToFile = InstallNewFile(WorkspaceDir, FromFile)\r
272 ContentZipFile.UnpackFile(FromFile, ToFile)\r
273\r
274 # update database\r
275 EdkLogger.quiet("Update Distribution Package Database ...")\r
276 Db.AddDPObject(DistPkg)\r
277\r
278 except FatalError, X:\r
279 if Options and Options.LogLevel < EdkLogger.DEBUG_9:\r
280 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
281 ReturnCode = X.args[0]\r
282 except KeyboardInterrupt:\r
283 ReturnCode = ABORT_ERROR\r
284 if Options and Options.LogLevel < EdkLogger.DEBUG_9:\r
285 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
286 except:\r
287 EdkLogger.error(\r
288 "\nInstallPkg",\r
289 CODE_ERROR,\r
290 "Unknown fatal error when installing [%s]" % Options.PackageFile,\r
52302d4d 291 ExtraData="\n(Please send email to edk2-buildtools-devel@lists.sourceforge.net for help, attaching following call stack trace!)\n",\r
30fdf114
LG
292 RaiseError=False\r
293 )\r
294 EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
295 ReturnCode = CODE_ERROR\r
296 finally:\r
297 EdkLogger.quiet("Removing temp files ... ")\r
298 if DistFile:\r
299 DistFile.Close()\r
300 if ContentZipFile:\r
301 ContentZipFile.Close()\r
302 if UnpackDir:\r
303 shutil.rmtree(UnpackDir)\r
304 \r
305 EdkLogger.quiet("DONE")\r
306 Progressor.Abort()\r
307\r
308if __name__ == '__main__':\r
309 sys.exit(Main())\r