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