]>
Commit | Line | Data |
---|---|---|
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 | |
17 | import os\r | |
18 | import sys\r | |
19 | import glob\r | |
20 | import shutil\r | |
21 | import traceback\r | |
22 | import platform\r | |
23 | from optparse import OptionParser\r | |
24 | \r | |
25 | import Common.EdkLogger as EdkLogger\r | |
26 | from Common.BuildToolError import *\r | |
27 | from Common.Misc import *\r | |
28 | from Common.XmlParser import *\r | |
29 | from Common.InfClassObjectLight import Inf\r | |
30 | from Common.DecClassObjectLight import Dec\r | |
31 | \r | |
32 | from PackageFile import *\r | |
33 | from IpiDb import *\r | |
34 | from DependencyRules import *\r | |
35 | import md5\r | |
36 | \r | |
37 | # Version and Copyright\r | |
38 | VersionNumber = "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 | |
53 | def 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 | |
74 | def 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 | |
105 | def 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 | |
118 | def 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 | |
140 | def 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 | |
308 | if __name__ == '__main__':\r | |
309 | sys.exit(Main())\r |