git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10123 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			310 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			310 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| ## @file
 | |
| # Install distribution package.
 | |
| #
 | |
| # Copyright (c) 2007, Intel Corporation
 | |
| # All rights reserved. This program and the accompanying materials
 | |
| # are licensed and made available under the terms and conditions of the BSD License
 | |
| # which accompanies this distribution.  The full text of the license may be found at
 | |
| # http://opensource.org/licenses/bsd-license.php
 | |
| #
 | |
| # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| #
 | |
| 
 | |
| ##
 | |
| # Import Modules
 | |
| #
 | |
| import os
 | |
| import sys
 | |
| import glob
 | |
| import shutil
 | |
| import traceback
 | |
| import platform
 | |
| from optparse import OptionParser
 | |
| 
 | |
| import Common.EdkLogger as EdkLogger
 | |
| from Common.BuildToolError import *
 | |
| from Common.Misc import *
 | |
| from Common.XmlParser import *
 | |
| from Common.InfClassObjectLight import Inf
 | |
| from Common.DecClassObjectLight import Dec
 | |
| 
 | |
| from PackageFile import *
 | |
| from IpiDb import *
 | |
| from DependencyRules import *
 | |
| import md5
 | |
| 
 | |
| # Version and Copyright
 | |
| VersionNumber = "0.1"
 | |
| __version__ = "%prog Version " + VersionNumber
 | |
| __copyright__ = "Copyright (c) 2008, Intel Corporation  All rights reserved."
 | |
| 
 | |
| ## Check environment variables
 | |
| #
 | |
| #  Check environment variables that must be set for build. Currently they are
 | |
| #
 | |
| #   WORKSPACE           The directory all packages/platforms start from
 | |
| #   EDK_TOOLS_PATH      The directory contains all tools needed by the build
 | |
| #   PATH                $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH
 | |
| #
 | |
| #   If any of above environment variable is not set or has error, the build
 | |
| #   will be broken.
 | |
| #
 | |
| def CheckEnvVariable():
 | |
|     # check WORKSPACE
 | |
|     if "WORKSPACE" not in os.environ:
 | |
|         EdkLogger.error("InstallPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",
 | |
|                         ExtraData="WORKSPACE")
 | |
| 
 | |
|     WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"])
 | |
|     if not os.path.exists(WorkspaceDir):
 | |
|         EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir)
 | |
|     elif ' ' in WorkspaceDir:
 | |
|         EdkLogger.error("InstallPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", 
 | |
|                         ExtraData=WorkspaceDir)
 | |
|     os.environ["WORKSPACE"] = WorkspaceDir
 | |
| 
 | |
| ## Parse command line options
 | |
| #
 | |
| # Using standard Python module optparse to parse command line option of this tool.
 | |
| #
 | |
| #   @retval Opt   A optparse.Values object containing the parsed options
 | |
| #   @retval Args  Target of build command
 | |
| #
 | |
| def MyOptionParser():
 | |
|     UsageString = "%prog -i <distribution_package> [-t] [-f] [-q | -v] [-h]"
 | |
| 
 | |
|     Parser = OptionParser(description=__copyright__,version=__version__,prog="InstallPkg",usage=UsageString)
 | |
| 
 | |
|     Parser.add_option("-?", action="help", help="show this help message and exit")
 | |
| 
 | |
|     Parser.add_option("-i", "--distribution-package", action="store", type="string", dest="PackageFile",
 | |
|             help="The distribution package to be installed")
 | |
| 
 | |
|     Parser.add_option("-t", "--install-tools", action="store_true", type=None, dest="Tools",
 | |
|             help="Specify it to install tools or ignore the tools of the distribution package.")
 | |
|     
 | |
|     Parser.add_option("-f", "--misc-files", action="store_true", type=None, dest="MiscFiles",
 | |
|             help="Specify it to install misc file or ignore the misc files of the distribution package.")
 | |
| 
 | |
|     Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET,
 | |
|             help="Disable all messages except FATAL ERRORS.")
 | |
| 
 | |
|     Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE,
 | |
|             help="Turn on verbose output")
 | |
| 
 | |
|     Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel",
 | |
|             help="Enable debug messages at specified level.")
 | |
| 
 | |
|     Parser.set_defaults(LogLevel=EdkLogger.INFO)
 | |
| 
 | |
|     (Opt, Args)=Parser.parse_args()
 | |
| 
 | |
|     return Opt
 | |
| 
 | |
| def InstallNewPackage(WorkspaceDir, Path):
 | |
|     FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path))
 | |
|     if os.path.exists(FullPath):
 | |
|         print "Directory [%s] already exists, please select another location, press [Enter] with no input to quit:" %Path
 | |
|         Input = sys.stdin.readline()
 | |
|         Input = Input.replace('\r', '').replace('\n', '')
 | |
|         if Input == '':
 | |
|             EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "User interrupt")
 | |
|         Input = Input.replace('\r', '').replace('\n', '')
 | |
|         return InstallNewPackage(WorkspaceDir, Input)
 | |
|     else:
 | |
|         return Path
 | |
| 
 | |
| def InstallNewFile(WorkspaceDir, File):
 | |
|     FullPath = os.path.normpath(os.path.join(WorkspaceDir, File))
 | |
|     if os.path.exists(FullPath):
 | |
|         print "File [%s] already exists, please select another path, press [Enter] with no input to quit:" %File
 | |
|         Input = sys.stdin.readline()
 | |
|         Input = Input.replace('\r', '').replace('\n', '')
 | |
|         if Input == '':
 | |
|             EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "User interrupt")
 | |
|         Input = Input.replace('\r', '').replace('\n', '')
 | |
|         return InstallNewFile(WorkspaceDir, Input)
 | |
|     else:
 | |
|         return File
 | |
| 
 | |
| ## Tool entrance method
 | |
| #
 | |
| # This method mainly dispatch specific methods per the command line options.
 | |
| # If no error found, return zero value so the caller of this tool can know
 | |
| # if it's executed successfully or not.
 | |
| #
 | |
| #   @retval 0     Tool was successful
 | |
| #   @retval 1     Tool failed
 | |
| #
 | |
| def Main():
 | |
|     EdkLogger.Initialize()
 | |
|     Options = None
 | |
|     DistFileName = 'dist.pkg'
 | |
|     ContentFileName = 'content.zip'
 | |
|     DistFile, ContentZipFile, UnpackDir = None, None, None
 | |
|     
 | |
|     Options = MyOptionParser()
 | |
|     try:
 | |
|         if Options.LogLevel < EdkLogger.DEBUG_9:
 | |
|             EdkLogger.SetLevel(Options.LogLevel + 1)
 | |
|         else:
 | |
|             EdkLogger.SetLevel(Options.LogLevel)
 | |
| 
 | |
|         CheckEnvVariable()
 | |
|         WorkspaceDir = os.environ["WORKSPACE"]
 | |
|         if not Options.PackageFile:
 | |
|             EdkLogger.error("InstallPkg", OPTION_NOT_SUPPORTED, ExtraData="Must specify one distribution package")
 | |
| 
 | |
|         # unzip dist.pkg file
 | |
|         EdkLogger.quiet("Unzipping and parsing distribution package XML file ... ")
 | |
|         DistFile = PackageFile(Options.PackageFile)
 | |
|         UnpackDir = os.path.normpath(os.path.join(WorkspaceDir, ".tmp"))
 | |
|         DistPkgFile = DistFile.UnpackFile(DistFileName, os.path.normpath(os.path.join(UnpackDir, DistFileName)))
 | |
|         if not DistPkgFile:
 | |
|             EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "File [%s] is broken in distribution package" %DistFileName)
 | |
|         
 | |
|         # Generate distpkg
 | |
|         DistPkgObj = DistributionPackageXml()
 | |
|         DistPkg = DistPkgObj.FromXml(DistPkgFile)
 | |
| 
 | |
|         # prepare check dependency
 | |
|         Db = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, "Conf/DistributionPackageDatabase.db")))
 | |
|         Db.InitDatabase()
 | |
|         Dep = DependencyRules(Db)
 | |
|         
 | |
|         # Check distribution package exist
 | |
|         if Dep.CheckDpExists(DistPkg.Header.Guid, DistPkg.Header.Version):
 | |
|             EdkLogger.error("InstallPkg", UNKNOWN_ERROR, "This distribution package has been installed", ExtraData=DistPkg.Header.Name)
 | |
|         
 | |
|         # unzip contents.zip file
 | |
|         ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(UnpackDir, ContentFileName)))
 | |
|         ContentZipFile = PackageFile(ContentFile)
 | |
|         if not ContentFile:
 | |
|             EdkLogger.error("InstallPkg", FILE_NOT_FOUND, "File [%s] is broken in distribution package" %ContentFileName)
 | |
|         
 | |
|         # verify MD5 signature
 | |
|         Md5Sigature = md5.new(open(ContentFile).read())
 | |
|         if DistPkg.Header.Signature != Md5Sigature.hexdigest():
 | |
|             EdkLogger.error("InstallPkg", FILE_CHECKSUM_FAILURE, ExtraData=ContentFile)
 | |
|         
 | |
|         # Check package exist and install
 | |
|         for Guid,Version,Path in DistPkg.PackageSurfaceArea:
 | |
|             PackagePath = os.path.dirname(Path)
 | |
|             NewPackagePath = PackagePath
 | |
|             Package = DistPkg.PackageSurfaceArea[Guid,Version,Path]
 | |
|             EdkLogger.info("Installing package ... %s" % Package.PackageHeader.Name)
 | |
|             if Dep.CheckPackageExists(Guid, Version):
 | |
|                 EdkLogger.quiet("Package [%s] has been installed" %Path)
 | |
|             NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath)
 | |
|             Package.FileList = []
 | |
|             for Item in Package.MiscFiles.Files:
 | |
|                 FromFile = os.path.join(PackagePath, Item.Filename)
 | |
|                 ToFile = os.path.normpath(os.path.join(WorkspaceDir, NewPackagePath, Item.Filename))
 | |
|                 ContentZipFile.UnpackFile(FromFile, ToFile)
 | |
|                 Package.FileList.append(ToFile)
 | |
|             
 | |
|             # Update package
 | |
|             Package.PackageHeader.CombinePath = Package.PackageHeader.CombinePath.replace(PackagePath, NewPackagePath, 1)
 | |
|             # Update modules of package
 | |
|             Module = None
 | |
|             for ModuleGuid, ModuleVersion, ModulePath in Package.Modules:
 | |
|                 Module = Package.Modules[ModuleGuid, ModuleVersion, ModulePath]
 | |
|                 NewModulePath = ModulePath.replace(PackagePath, NewPackagePath, 1)
 | |
|                 del Package.Modules[ModuleGuid, ModuleVersion, ModulePath]
 | |
|                 Package.Modules[ModuleGuid, ModuleVersion, NewModulePath] = Module
 | |
|             del DistPkg.PackageSurfaceArea[Guid,Version,Path]
 | |
|             DistPkg.PackageSurfaceArea[Guid,Version,Package.PackageHeader.CombinePath] = Package
 | |
| 
 | |
| #            SaveFileOnChange(os.path.join(Options.InstallDir, ModulePath, Module.Header.Name, ".inf"), Inf.ModuleToInf(Module), False)
 | |
| #            EdkLogger.info("Installing package ... %s" % Package.Header.Name)
 | |
| #            shutil.copytree(os.path.join(ContentFileDir, Path), Options.InstallDir)
 | |
| #            SaveFileOnChange(os.path.join(Options.InstallDir, Path, Package.Header.Name, ".dec"), Dec.PackageToDec(Package), False)
 | |
| 
 | |
|         # Check module exist and install
 | |
|         Module = None
 | |
|         for Guid,Version,Path in DistPkg.ModuleSurfaceArea:
 | |
|             ModulePath = os.path.dirname(Path)
 | |
|             NewModulePath = ModulePath
 | |
|             Module = DistPkg.ModuleSurfaceArea[Guid,Version,Path]
 | |
|             EdkLogger.info("Installing module ... %s" % Module.ModuleHeader.Name)
 | |
|             if Dep.CheckModuleExists(Guid, Version):
 | |
|                 EdkLogger.quiet("Module [%s] has been installed" %Path)
 | |
|             NewModulePath = InstallNewPackage(WorkspaceDir, ModulePath)
 | |
|             Module.FileList = []
 | |
|             for Item in Module.MiscFiles.Files:
 | |
|                 ModulePath = ModulePath[os.path.normpath(ModulePath).rfind(os.path.normpath('/'))+1:]
 | |
|                 FromFile = os.path.join(ModulePath, Item.Filename)
 | |
|                 ToFile = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath, Item.Filename))
 | |
|                 ContentZipFile.UnpackFile(FromFile, ToFile)
 | |
|                 Module.FileList.append(ToFile)
 | |
|             
 | |
| #            EdkLogger.info("Installing module ... %s" % Module.Header.Name)
 | |
| #            shutil.copytree(os.path.join(ContentFileDir, Path), Options.InstallDir)
 | |
| #            SaveFileOnChange(os.path.join(Options.InstallDir, Path, Module.Header.Name, ".inf"), Inf.ModuleToInf(Module), False)
 | |
|             
 | |
|             # Update module
 | |
|             Module.ModuleHeader.CombinePath = Module.ModuleHeader.CombinePath.replace(os.path.dirname(Path), NewModulePath, 1)
 | |
|             del DistPkg.ModuleSurfaceArea[Guid,Version,Path]
 | |
|             DistPkg.ModuleSurfaceArea[Guid,Version,Module.ModuleHeader.CombinePath] = Module
 | |
| #            
 | |
| #        
 | |
| #        for Guid,Version,Path in DistPkg.PackageSurfaceArea:
 | |
| #            print Guid,Version,Path
 | |
| #            for item in DistPkg.PackageSurfaceArea[Guid,Version,Path].FileList:
 | |
| #                print item
 | |
| #        for Guid,Version,Path in DistPkg.ModuleSurfaceArea:
 | |
| #            print Guid,Version,Path
 | |
| #            for item in DistPkg.ModuleSurfaceArea[Guid,Version,Path].FileList:
 | |
| #                print item
 | |
| 
 | |
|         if Options.Tools:
 | |
|             EdkLogger.info("Installing tools ... ")
 | |
|             for File in DistPkg.Tools.Files:
 | |
|                 FromFile = File.Filename
 | |
|                 ToFile = InstallNewFile(WorkspaceDir, FromFile)
 | |
|                 ContentZipFile.UnpackFile(FromFile, ToFile)
 | |
|         if Options.MiscFiles:
 | |
|             EdkLogger.info("Installing misc files ... ")
 | |
|             for File in DistPkg.MiscellaneousFiles.Files:
 | |
|                 FromFile = File.Filename
 | |
|                 ToFile = InstallNewFile(WorkspaceDir, FromFile)
 | |
|                 ContentZipFile.UnpackFile(FromFile, ToFile)
 | |
| 
 | |
|         # update database
 | |
|         EdkLogger.quiet("Update Distribution Package Database ...")
 | |
|         Db.AddDPObject(DistPkg)
 | |
| 
 | |
|     except FatalError, X:
 | |
|         if Options and Options.LogLevel < EdkLogger.DEBUG_9:
 | |
|             EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
 | |
|         ReturnCode = X.args[0]
 | |
|     except KeyboardInterrupt:
 | |
|         ReturnCode = ABORT_ERROR
 | |
|         if Options and Options.LogLevel < EdkLogger.DEBUG_9:
 | |
|             EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
 | |
|     except:
 | |
|         EdkLogger.error(
 | |
|                     "\nInstallPkg",
 | |
|                     CODE_ERROR,
 | |
|                     "Unknown fatal error when installing [%s]" % Options.PackageFile,
 | |
|                     ExtraData="\n(Please send email to edk2-buildtools-devel@lists.sourceforge.net for help, attaching following call stack trace!)\n",
 | |
|                     RaiseError=False
 | |
|                     )
 | |
|         EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
 | |
|         ReturnCode = CODE_ERROR
 | |
|     finally:
 | |
|         EdkLogger.quiet("Removing temp files ... ")
 | |
|         if DistFile:
 | |
|             DistFile.Close()
 | |
|         if ContentZipFile:
 | |
|             ContentZipFile.Close()
 | |
|         if UnpackDir:
 | |
|             shutil.rmtree(UnpackDir)
 | |
|         
 | |
|         EdkLogger.quiet("DONE")
 | |
|         Progressor.Abort()
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     sys.exit(Main())
 |