From 30fdf1140b8d1ce93f3821d986fa165552023440 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Fri, 17 Jul 2009 09:10:31 +0000 Subject: Check In tool source code based on Build tool project revision r1655. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Source/Python/PackagingTool/DependencyRules.py | 185 ++++++ .../Source/Python/PackagingTool/InstallPkg.py | 309 ++++++++++ BaseTools/Source/Python/PackagingTool/IpiDb.py | 629 +++++++++++++++++++++ BaseTools/Source/Python/PackagingTool/MkPkg.py | 294 ++++++++++ .../Source/Python/PackagingTool/PackageFile.py | 160 ++++++ BaseTools/Source/Python/PackagingTool/RmPkg.py | 218 +++++++ 6 files changed, 1795 insertions(+) create mode 100644 BaseTools/Source/Python/PackagingTool/DependencyRules.py create mode 100644 BaseTools/Source/Python/PackagingTool/InstallPkg.py create mode 100644 BaseTools/Source/Python/PackagingTool/IpiDb.py create mode 100644 BaseTools/Source/Python/PackagingTool/MkPkg.py create mode 100644 BaseTools/Source/Python/PackagingTool/PackageFile.py create mode 100644 BaseTools/Source/Python/PackagingTool/RmPkg.py (limited to 'BaseTools/Source/Python/PackagingTool') diff --git a/BaseTools/Source/Python/PackagingTool/DependencyRules.py b/BaseTools/Source/Python/PackagingTool/DependencyRules.py new file mode 100644 index 0000000000..402694054e --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/DependencyRules.py @@ -0,0 +1,185 @@ +## @file +# This file is for installed package information database operations +# +# Copyright (c) 2007 ~ 2008, 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 sqlite3 +import os + +import Common.EdkLogger as EdkLogger +import IpiDb + +(DEPEX_CHECK_SUCCESS, DEPEX_CHECK_MODULE_NOT_FOUND, \ +DEPEX_CHECK_PACKAGE_NOT_FOUND, DEPEX_CHECK_DP_NOT_FOUND) = (0, 1, 2, 3) + +## IpiDb +# +# This class represents the installed package information databse +# Add/Remove/Get installed distribution package information here. +# +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the database +# +# @var Conn: Connection of the database +# @var Cur: Cursor of the connection +# +class DependencyRules(object): + def __init__(self, Db): + self.IpiDb = Db + + ## Check whether a module exists in current workspace. + # + # @param Guid: + # @param Version: + # + def CheckModuleExists(self, Guid, Version, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck module exists in workspace started ...") + ModuleList = [] + ModuleList = self.IpiDb.GetModInPackage(Guid, Version) + ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version)) + EdkLogger.verbose("Check module exists in workspace ... DONE!") + if len(ModuleList) > 0: + return True + else: + ReturnCode = DEPEX_CHECK_MODULE_NOT_FOUND + return False + + + ## Check whether a module depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckModuleDepexSatisfied(self, ModuleObj, DpObj = None, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck module depex met by workspace started ...") + for Dep in ModuleObj.PackageDependencies: + Exist = self.CheckPackageExists(Dep.PackageGuid, Dep.PackageVersion, ReturnCode) + if not Exist: + if DpObj == None: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + for GuidVerPair in DpObj.PackageSurfaceArea.keys(): + if Dep.PackageGuid == GuidVerPair[0]: + if Dep.PackageVersion == None or len(Dep.PackageVersion) == 0: + break + if Dep.PackageVersion == GuidVerPair[1]: + break + else: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + else: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + return True + + EdkLogger.verbose("Check module depex met by workspace ... DONE!") + + ## Check whether a package exists in current workspace. + # + # @param Guid: + # @param Version: + # + def CheckPackageExists(self, Guid, Version, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck package exists in workspace started ...") + PkgList = [] + PkgList = self.IpiDb.GetPackage(Guid, Version) + if len(PkgList) > 0: + return True + else: + ReturnCode = DEPEX_CHECK_PACKAGE_NOT_FOUND + return False + + EdkLogger.verbose("Check package exists in workspace ... DONE!") + + ## Check whether a package depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckPackageDepexSatisfied(self, PkgObj, DpObj = None, ReturnCode = DEPEX_CHECK_SUCCESS): + + for ModKey in PkgObj.Modules.keys(): + ModObj = PkgObj.Modules[ModKey] + if self.CheckModuleDepexSatisfied(ModObj, DpObj, ReturnCode): + continue + else: + return False + return True + + ## Check whether a DP exists in current workspace. + # + # @param Guid: + # @param Version: + # + def CheckDpExists(self, Guid, Version, ReturnCode = DEPEX_CHECK_SUCCESS): + EdkLogger.verbose("\nCheck DP exists in workspace started ...") + DpList = [] + DpList = self.IpiDb.GetDp(Guid, Version) + if len(DpList) > 0: + return True + else: + ReturnCode = DEPEX_CHECK_DP_NOT_FOUND + return False + + EdkLogger.verbose("Check DP exists in workspace ... DONE!") + + ## Check whether a DP depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckDpDepexSatisfied(self, DpObj, ReturnCode = DEPEX_CHECK_SUCCESS): + + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + if self.CheckPackageDepexSatisfied(PkgObj, DpObj, ReturnCode): + continue + else: + return False + + for ModKey in DpObj.ModuleSurfaceArea.keys(): + ModObj = PkgObj.ModuleSurfaceArea[ModKey] + if self.CheckModuleDepexSatisfied(ModObj, DpObj, ReturnCode): + continue + else: + return False + + return True + + ## Check whether a DP depex satified by current workspace. + # + # @param ModuleObj: + # @param DpObj: + # + def CheckDpDepexForRemove(self, DpGuid, DpVersion, ReturnCode = DEPEX_CHECK_SUCCESS): + + # Get mod list that is dependent on pkg installed from this DP. + ModList = self.IpiDb.GetDpDependentModuleList(DpGuid, DpVersion) + + if len(ModList) > 0: + return False + + return True +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + + + \ No newline at end of file diff --git a/BaseTools/Source/Python/PackagingTool/InstallPkg.py b/BaseTools/Source/Python/PackagingTool/InstallPkg.py new file mode 100644 index 0000000000..963a654ea1 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/InstallPkg.py @@ -0,0 +1,309 @@ +## @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/ 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 [-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 dev@buildtools.tianocore.org 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()) diff --git a/BaseTools/Source/Python/PackagingTool/IpiDb.py b/BaseTools/Source/Python/PackagingTool/IpiDb.py new file mode 100644 index 0000000000..8661edbca4 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/IpiDb.py @@ -0,0 +1,629 @@ +## @file +# This file is for installed package information database operations +# +# Copyright (c) 2007 ~ 2008, 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 sqlite3 +import os +import time +import Common.EdkLogger as EdkLogger + +from CommonDataClass import DistributionPackageClass + +## IpiDb +# +# This class represents the installed package information databse +# Add/Remove/Get installed distribution package information here. +# +# +# @param object: Inherited from object class +# @param DbPath: A string for the path of the database +# +# @var Conn: Connection of the database +# @var Cur: Cursor of the connection +# +class IpiDatabase(object): + def __init__(self, DbPath): + Dir = os.path.dirname(DbPath) + if not os.path.isdir(Dir): + os.mkdir(Dir) + self.Conn = sqlite3.connect(DbPath, isolation_level = 'DEFERRED') + self.Conn.execute("PRAGMA page_size=4096") + self.Conn.execute("PRAGMA synchronous=OFF") + self.Cur = self.Conn.cursor() + self.DpTable = 'DpInfo' + self.PkgTable = 'PkgInfo' + self.ModInPkgTable = 'ModInPkgInfo' + self.StandaloneModTable = 'StandaloneModInfo' + self.ModDepexTable = 'ModDepexInfo' + self.DpFileListTable = 'DpFileListInfo' + + ## Initialize build database + # + # + def InitDatabase(self): + EdkLogger.verbose("\nInitialize IPI database started ...") + + # + # Create new table + # + SqlCommand = """create table IF NOT EXISTS %s (DpGuid TEXT NOT NULL, + DpVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + PkgFileName TEXT, + PRIMARY KEY (DpGuid, DpVersion) + )""" % self.DpTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (FilePath TEXT NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + PRIMARY KEY (FilePath) + )""" % self.DpFileListTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (PackageGuid TEXT NOT NULL, + PackageVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (PackageGuid, PackageVersion, InstallPath) + )""" % self.PkgTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + PackageGuid TEXT, + PackageVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (ModuleGuid, ModuleVersion, InstallPath) + )""" % self.ModInPkgTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + InstallTime REAL NOT NULL, + DpGuid TEXT, + DpVersion TEXT, + InstallPath TEXT NOT NULL, + PRIMARY KEY (ModuleGuid, ModuleVersion, InstallPath) + )""" % self.StandaloneModTable + self.Cur.execute(SqlCommand) + + SqlCommand = """create table IF NOT EXISTS %s (ModuleGuid TEXT NOT NULL, + ModuleVersion TEXT NOT NULL, + InstallPath TEXT NOT NULL, + DepexGuid TEXT, + DepexVersion TEXT + )""" % self.ModDepexTable + self.Cur.execute(SqlCommand) + + self.Conn.commit() + + EdkLogger.verbose("Initialize IPI database ... DONE!") + + ## Add a distribution install information from DpObj + # + # @param DpObj: + # + def AddDPObject(self, DpObj): + + for PkgKey in DpObj.PackageSurfaceArea.keys(): + PkgGuid = PkgKey[0] + PkgVersion = PkgKey[1] + PkgInstallPath = PkgKey[2] + self.AddPackage(PkgGuid, PkgVersion, DpObj.Header.Guid, DpObj.Header.Version, PkgInstallPath) + PkgObj = DpObj.PackageSurfaceArea[PkgKey] + for ModKey in PkgObj.Modules.keys(): + ModGuid = ModKey[0] + ModVersion = ModKey[1] + ModInstallPath = ModKey[2] + self.AddModuleInPackage(ModGuid, ModVersion, PkgGuid, PkgVersion, ModInstallPath) + ModObj = PkgObj.Modules[ModKey] + for Dep in ModObj.PackageDependencies: + DepexGuid = Dep.PackageGuid + DepexVersion = Dep.PackageVersion + self.AddModuleDepex(ModGuid, ModVersion, ModInstallPath, DepexGuid, DepexVersion) + for FilePath in PkgObj.FileList: + self.AddDpFilePathList(DpObj.Header.Guid, DpObj.Header.Version, FilePath) + + for ModKey in DpObj.ModuleSurfaceArea.keys(): + ModGuid = ModKey[0] + ModVersion = ModKey[1] + ModInstallPath = ModKey[2] + self.AddStandaloneModule(ModGuid, ModVersion, DpObj.Header.Guid, DpObj.Header.Version, ModInstallPath) + ModObj = DpObj.ModuleSurfaceArea[ModKey] + for Dep in ModObj.PackageDependencies: + DepexGuid = Dep.PackageGuid + DepexVersion = Dep.PackageVersion + self.AddModuleDepex(ModGuid, ModVersion, ModInstallPath, DepexGuid, DepexVersion) + for FilePath in ModObj.FileList: + self.AddDpFilePathList(DpObj.Header.Guid, DpObj.Header.Version, FilePath) + + self.AddDp(DpObj.Header.Guid, DpObj.Header.Version, DpObj.Header.FileName) + ## Add a distribution install information + # + # @param Guid: + # @param Version: + # @param PkgFileName: + # + def AddDp(self, Guid, Version, PkgFileName = None): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + # + # Add newly installed DP information to DB. + # + if PkgFileName == None or len(PkgFileName.strip()) == 0: + PkgFileName = 'N/A' + (Guid, Version, PkgFileName) = (Guid, Version, PkgFileName) + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s')""" % (self.DpTable, Guid, Version, CurrentTime, PkgFileName) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a file list from DP + # + # @param DpGuid: + # @param DpVersion: + # @param Path + # + def AddDpFilePathList(self, DpGuid, DpVersion, Path): + + SqlCommand = """insert into %s values('%s', '%s', '%s')""" % (self.DpFileListTable, Path, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a package install information + # + # @param Guid: + # @param Version: + # @param DpGuid: + # @param DpVersion: + # @param Path + # + def AddPackage(self, Guid, Version, DpGuid = None, DpVersion = None, Path = ''): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + if DpGuid == None or len(DpGuid.strip()) == 0: + DpGuid = 'N/A' + + if DpVersion == None or len(DpVersion.strip()) == 0: + DpVersion = 'N/A' + + # + # Add newly installed package information to DB. + # + + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % (self.PkgTable, Guid, Version, CurrentTime, DpGuid, DpVersion, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a module that from a package install information + # + # @param Guid: + # @param Version: + # @param PkgFileName: + # + def AddModuleInPackage(self, Guid, Version, PkgGuid = None, PkgVersion = None, Path = ''): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + if PkgGuid == None or len(PkgGuid.strip()) == 0: + PkgGuid = 'N/A' + + if PkgVersion == None or len(PkgVersion.strip()) == 0: + PkgVersion = 'N/A' + + # + # Add module from package information to DB. + # + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % (self.ModInPkgTable, Guid, Version, CurrentTime, PkgGuid, PkgVersion, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a module that is standalone install information + # + # @param Guid: + # @param Version: + # @param PkgFileName: + # + def AddStandaloneModule(self, Guid, Version, DpGuid = None, DpVersion = None, Path = ''): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + + if DpGuid == None or len(DpGuid.strip()) == 0: + DpGuid = 'N/A' + + if DpVersion == None or len(DpVersion.strip()) == 0: + DpVersion = 'N/A' + + # + # Add module standalone information to DB. + # + CurrentTime = time.time() + SqlCommand = """insert into %s values('%s', '%s', %s, '%s', '%s', '%s')""" % (self.StandaloneModTable, Guid, Version, CurrentTime, DpGuid, DpVersion, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Add a module depex + # + # @param Guid: + # @param Version: + # @param DepexGuid: + # @param DepexVersion: + # + def AddModuleDepex(self, Guid, Version, Path, DepexGuid = None, DepexVersion = None): + + if DepexGuid == None or len(DepexGuid.strip()) == 0: + DepexGuid = 'N/A' + + if DepexVersion == None or len(DepexVersion.strip()) == 0: + DepexVersion = 'N/A' + + # + # Add module depex information to DB. + # + + SqlCommand = """insert into %s values('%s', '%s', '%s', '%s', '%s')""" % (self.ModDepexTable, Guid, Version, Path, DepexGuid, DepexVersion) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + ## Remove a distribution install information, if no version specified, remove all DPs with this Guid. + # + # @param DpObj: + # + def RemoveDpObj(self, DpGuid, DpVersion): + + PkgList = self.GetPackageListFromDp(DpGuid, DpVersion) + + # delete from ModDepex the standalone module's dependency + SqlCommand = """delete from ModDepexInfo where ModDepexInfo.ModuleGuid in + (select ModuleGuid from StandaloneModInfo as B where B.DpGuid = '%s' and B.DpVersion = '%s') + and ModDepexInfo.ModuleVersion in + (select ModuleVersion from StandaloneModInfo as B where B.DpGuid = '%s' and B.DpVersion = '%s') + and ModDepexInfo.InstallPath in + (select InstallPath from StandaloneModInfo as B where B.DpGuid = '%s' and B.DpVersion = '%s') """ \ + %(DpGuid, DpVersion, DpGuid, DpVersion, DpGuid, DpVersion) + +# SqlCommand = """delete from %s where %s.DpGuid ='%s' and %s.DpVersion = '%s' and +# %s.ModuleGuid = %s.ModuleGuid and %s.ModuleVersion = %s.ModuleVersion and +# %s.InstallPath = %s.InstallPath""" \ +# % (self.ModDepexTable, self.StandaloneModTable, DpGuid, self.StandaloneModTable, DpVersion, self.ModDepexTable, self.StandaloneModTable, self.ModDepexTable, self.StandaloneModTable, self.ModDepexTable, self.StandaloneModTable) +# print SqlCommand + self.Cur.execute(SqlCommand) + + # delete from ModDepex the from pkg module's dependency + for Pkg in PkgList: +# SqlCommand = """delete from %s where %s.PackageGuid ='%s' and %s.PackageVersion = '%s' and +# %s.ModuleGuid = %s.ModuleGuid and %s.ModuleVersion = %s.ModuleVersion and +# %s.InstallPath = %s.InstallPath""" \ +# % (self.ModDepexTable, self.ModInPkgTable, Pkg[0], self.ModInPkgTable, Pkg[1], self.ModDepexTable, self.ModInPkgTable, self.ModDepexTable, self.ModInPkgTable, self.ModDepexTable, self.ModInPkgTable) + SqlCommand = """delete from ModDepexInfo where ModDepexInfo.ModuleGuid in + (select ModuleGuid from ModInPkgInfo where ModInPkgInfo.PackageGuid ='%s' and ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.ModuleVersion in + (select ModuleVersion from ModInPkgInfo where ModInPkgInfo.PackageGuid ='%s' and ModInPkgInfo.PackageVersion = '%s') + and ModDepexInfo.InstallPath in + (select InstallPath from ModInPkgInfo where ModInPkgInfo.PackageGuid ='%s' and ModInPkgInfo.PackageVersion = '%s')""" \ + % (Pkg[0], Pkg[1],Pkg[0], Pkg[1],Pkg[0], Pkg[1]) + + self.Cur.execute(SqlCommand) + + # delete the standalone module + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.StandaloneModTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + # delete the from pkg module + for Pkg in PkgList: + SqlCommand = """delete from %s where %s.PackageGuid ='%s' and %s.PackageVersion = '%s'""" \ + % (self.ModInPkgTable, self.ModInPkgTable, Pkg[0], self.ModInPkgTable, Pkg[1]) + self.Cur.execute(SqlCommand) + + # delete packages + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.PkgTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + # delete file list from DP + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + # delete DP + SqlCommand = """delete from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + self.Conn.commit() + + ## Get a list of distribution install information. + # + # @param Guid: + # @param Version: + # + def GetDp(self, Guid, Version): + + if Version == None or len(Version.strip()) == 0: + Version = 'N/A' + EdkLogger.verbose("\nGetting list of DP install information started ...") + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s'""" % (self.DpTable, DpGuid) + self.Cur.execute(SqlCommand) + + else: + EdkLogger.verbose("\nGetting DP install information started ...") + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + DpList = [] + for DpInfo in self.Cur: + DpGuid = DpInfo[0] + DpVersion = DpInfo[1] + InstallTime = DpInfo[2] + PkgFileName = DpInfo[3] + DpList.append((DpGuid, DpVersion, InstallTime, PkgFileName)) + + EdkLogger.verbose("Getting DP install information ... DONE!") + return DpList + + ## Get a list of distribution install file path information. + # + # @param Guid: + # @param Version: + # + def GetDpFileList(self, Guid, Version): + + (DpGuid, DpVersion) = (Guid, Version) + SqlCommand = """select * from %s where DpGuid ='%s' and DpVersion = '%s'""" % (self.DpFileListTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PathList = [] + for Result in self.Cur: + Path = Result[0] + PathList.append(Path) + + return PathList + + ## Get a list of package information. + # + # @param Guid: + # @param Version: + # + def GetPackage(self, Guid, Version, DpGuid = '', DpVersion = ''): + + if DpVersion == '' or DpGuid == '': + + (PackageGuid, PackageVersion) = (Guid, Version) + SqlCommand = """select * from %s where PackageGuid ='%s' and PackageVersion = '%s'""" % (self.PkgTable, PackageGuid, PackageVersion) + self.Cur.execute(SqlCommand) + + elif Version == None or len(Version.strip()) == 0: + + SqlCommand = """select * from %s where PackageGuid ='%s'""" % (self.PkgTable, Guid) + self.Cur.execute(SqlCommand) + else: + (PackageGuid, PackageVersion) = (Guid, Version) + SqlCommand = """select * from %s where PackageGuid ='%s' and PackageVersion = '%s' + and DpGuid = '%s' and DpVersion = '%s'""" % (self.PkgTable, PackageGuid, PackageVersion, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PkgList = [] + for PkgInfo in self.Cur: + PkgGuid = PkgInfo[0] + PkgVersion = PkgInfo[1] + InstallTime = PkgInfo[2] + InstallPath = PkgInfo[5] + PkgList.append((PkgGuid, PkgVersion, InstallTime, DpGuid, DpVersion, InstallPath)) + + return PkgList + + ## Get a list of module in package information. + # + # @param Guid: + # @param Version: + # + def GetModInPackage(self, Guid, Version, PkgGuid = '', PkgVersion = ''): + + if PkgVersion == '' or PkgGuid == '': + + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s'""" % (self.ModInPkgTable, ModuleGuid, ModuleVersion) + self.Cur.execute(SqlCommand) + + else: + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s' and PackageGuid ='%s' and PackageVersion = '%s' + """ % (self.ModInPkgTable, ModuleGuid, ModuleVersion, PkgGuid, PkgVersion) + self.Cur.execute(SqlCommand) + + ModList = [] + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallTime = ModInfo[2] + InstallPath = ModInfo[5] + ModList.append((ModGuid, ModVersion, InstallTime, PkgGuid, PkgVersion, InstallPath)) + + return ModList + + ## Get a list of module standalone. + # + # @param Guid: + # @param Version: + # + def GetStandaloneModule(self, Guid, Version, DpGuid = '', DpVersion = ''): + + if DpGuid == '': + + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s'""" % (self.StandaloneModTable, ModuleGuid, ModuleVersion) + self.Cur.execute(SqlCommand) + + else: + (ModuleGuid, ModuleVersion) = (Guid, Version) + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s' and DpGuid ='%s' and DpVersion = '%s' + """ % (self.StandaloneModTable, ModuleGuid, ModuleVersion, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + ModList = [] + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallTime = ModInfo[2] + InstallPath = ModInfo[5] + ModList.append((ModGuid, ModVersion, InstallTime, DpGuid, DpVersion, InstallPath)) + + return ModList + + ## Get a list of module information that comes from DP. + # + # @param DpGuid: + # @param DpVersion: + # + def GetStandaloneModuleInstallPathListFromDp(self, DpGuid, DpVersion): + + PathList = [] + SqlCommand = """select t1.InstallPath from %s t1 where t1.DpGuid ='%s' and t1.DpVersion = '%s' + """ % (self.StandaloneModTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + for Result in self.Cur: + InstallPath = Result[0] + PathList.append(InstallPath) + + return PathList + + ## Get a list of package information. + # + # @param DpGuid: + # @param DpVersion: + # + def GetPackageListFromDp(self, DpGuid, DpVersion): + + + SqlCommand = """select * from %s where DpGuid ='%s' and DpVersion = '%s' + """ % (self.PkgTable, DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + + PkgList = [] + for PkgInfo in self.Cur: + PkgGuid = PkgInfo[0] + PkgVersion = PkgInfo[1] + InstallPath = PkgInfo[5] + PkgList.append((PkgGuid, PkgVersion, InstallPath)) + + return PkgList + + ## Get a list of modules that depends on package information from a DP. + # + # @param DpGuid: + # @param DpVersion: + # + def GetDpDependentModuleList(self, DpGuid, DpVersion): + + ModList = [] + PkgList = self.GetPackageListFromDp(DpGuid, DpVersion) + if len(PkgList) > 0: + return ModList + + for Pkg in PkgList: + SqlCommand = """select t1.ModuleGuid, t1.ModuleVersion, t1.InstallPath + from %s as t1, %s as t2, where t1.ModuleGuid = t2.ModuleGuid and + t1.ModuleVersion = t2.ModuleVersion and t2.DepexGuid ='%s' and (t2.DepexVersion = '%s' or t2.DepexVersion = 'N/A') and + t1.PackageGuid != '%s' and t1.PackageVersion != '%s' + """ % (self.ModInPkgTable, self.ModDepexTable, Pkg[0], Pkg[1], Pkg[0], Pkg[1]) + self.Cur.execute(SqlCommand) + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallPath = ModInfo[2] + ModList.append((ModGuid, ModVersion, InstallPath)) + + SqlCommand = """select t1.ModuleGuid, t1.ModuleVersion, t1.InstallPath + from %s as t1, %s as t2, where t1.ModuleGuid = t2.ModuleGuid and + t1.ModuleVersion = t2.ModuleVersion and t2.DepexGuid ='%s' and (t2.DepexVersion = '%s' or t2.DepexVersion = 'N/A') and + t1.DpGuid != '%s' and t1.DpVersion != '%s' + """ % (self.StandaloneModTable, self.ModDepexTable, Pkg[0], Pkg[1], DpGuid, DpVersion) + self.Cur.execute(SqlCommand) + for ModInfo in self.Cur: + ModGuid = ModInfo[0] + ModVersion = ModInfo[1] + InstallPath = ModInfo[2] + ModList.append((ModGuid, ModVersion, InstallPath)) + + + return ModList + + ## Get a module depex + # + # @param Guid: + # @param Version: + # @param Path: + # + def GetModuleDepex(self, Guid, Version, Path): + + # + # Get module depex information to DB. + # + + SqlCommand = """select * from %s where ModuleGuid ='%s' and ModuleVersion = '%s' and InstallPath ='%s' + """ % (self.ModDepexTable, Guid, Version, Path) + self.Cur.execute(SqlCommand) + self.Conn.commit() + + DepexList = [] + for DepInfo in self.Cur: + DepexGuid = DepInfo[3] + DepexVersion = DepInfo[4] + DepexList.append((DepexGuid, DepexVersion)) + + return DepexList + + ## Close entire database + # + # Close the connection and cursor + # + def CloseDb(self): + + self.Cur.close() + self.Conn.close() + + ## Convert To Sql String + # + # 1. Replace "'" with "''" in each item of StringList + # + # @param StringList: A list for strings to be converted + # + def __ConvertToSqlString(self, StringList): + return map(lambda s: s.replace("'", "''") , StringList) +## +# +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +# +if __name__ == '__main__': + EdkLogger.Initialize() + EdkLogger.SetLevel(EdkLogger.DEBUG_0) + DATABASE_PATH = "C://MyWork//Conf//.cache//XML.db" + Db = IpiDatabase(DATABASE_PATH) + Db.InitDatabase() + + \ No newline at end of file diff --git a/BaseTools/Source/Python/PackagingTool/MkPkg.py b/BaseTools/Source/Python/PackagingTool/MkPkg.py new file mode 100644 index 0000000000..660f48f05f --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/MkPkg.py @@ -0,0 +1,294 @@ +## @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 os.path +import sys +import glob +import shutil +import traceback +import platform +from optparse import OptionParser +import md5 +import time +import uuid + +from PackageFile import * +import Common.EdkLogger as EdkLogger +from Common.BuildToolError import * +from Common.Misc import * +from Common.XmlParser import * +from CommonDataClass.DistributionPackageClass import * +from Common.DecClassObjectLight import Dec +from Common.InfClassObjectLight import Inf + +from PackageFile import * + +# 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/ 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("MkPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + + WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"]) + if not os.path.exists(WorkspaceDir): + EdkLogger.error("MkPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) + elif ' ' in WorkspaceDir: + EdkLogger.error("MkPkg", 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 -m -p [-o distribution_file] " + \ + "[-x xml-file-header] [-t tools-directory] [-f misc-files] [-q | -v] [-h]" + + Parser = OptionParser(description=__copyright__,version=__version__,prog="MkPkg",usage=UsageString) + + Parser.add_option("-?", action="help", help="show this help message and exit") + + Parser.add_option("-o", "--output-file", action="store", type="string", dest="DistributionFile", + help="Specify the distribution file to be created.") + + Parser.add_option("-f", "--misc-files", action="append", type="string", dest="MiscFiles", + help="Specify any misc files.") + + Parser.add_option("-x", "--xml-file-header", action="store", type=None, dest="TemplateFile", + help="Specify the xml file which includes header information for creating the distribution file.") + + Parser.add_option("-t", "--tools-directory", action="store", type=None, dest="ToolsDir", + help="Specify the directory name of tools.") + + Parser.add_option("-m", "--module", action="append", type="string", dest="ModuleFileList", + help="The inf file of module to be distributed standalone.") + + Parser.add_option("-p", "--package", action="append", type="string", dest="PackageFileList", + help="The dec file of package to be distributed.") + + 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() + # error check + if not Opt.ModuleFileList and not Opt.PackageFileList: + EdkLogger.error("MkPkg", OPTION_NOT_SUPPORTED, ExtraData="At least one package file or module file must be specified") + if Opt.TemplateFile: + if not os.path.exists(Opt.TemplateFile): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "Template file [%s] not found" % Opt.TemplateFile + ) + return Opt + +## 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 = MyOptionParser() + try: + if Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.SetLevel(Options.LogLevel + 1) + else: + EdkLogger.SetLevel(Options.LogLevel) + + CheckEnvVariable() + WorkspaceDir = os.environ["WORKSPACE"] + + # Init DistributionFile + if not Options.DistributionFile: + Options.DistributionFile = "DistributionPackage.zip" + + # Check Tools Dir + if Options.ToolsDir: + if not os.path.isdir(os.path.normpath(os.path.join(WorkspaceDir, Options.ToolsDir))): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "Tools directory [%s] not found" % Options.ToolsDir + ) + + # Check misc files + if Options.MiscFiles: + for Item in Options.MiscFiles: + FullPath = os.path.normpath(os.path.join(WorkspaceDir, Item)) + if not os.path.isfile(FullPath): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "Misc file [%s] not found" % Item + ) + + #Check package file existing and valid + if Options.PackageFileList: + for Item in Options.PackageFileList: + (Name, Ext) = os.path.splitext(Item) + if Ext.upper() != '.DEC': + EdkLogger.error( + "\nMkPkg", + OPTION_VALUE_INVALID, + "[%s] is not a valid package name" % Item + ) + Path = os.path.normpath(os.path.join(WorkspaceDir, Item)) + if not os.path.exists(Path): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "[%s] not found" % Item + ) + #Check module file existing and valid + if Options.ModuleFileList: + for Item in Options.ModuleFileList: + (Name, Ext) = os.path.splitext(Item) + if Ext.upper() != '.INF': + EdkLogger.error( + "\nMkPkg", + OPTION_VALUE_INVALID, + "[%s] is not a valid module name" % Item + ) + Path = os.path.normpath(os.path.join(WorkspaceDir, Item)) + if not os.path.exists(Path): + EdkLogger.error( + "\nMkPkg", + FILE_NOT_FOUND, + "[%s] not found" % Item + ) + + ContentFile = PackageFile("content.zip", "w") + DistPkg = DistributionPackageClass() + DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, Options.ModuleFileList) + DistPkgXml = DistributionPackageXml() + for Item in DistPkg.PackageSurfaceArea: + ContentFile.Pack(os.path.dirname(os.path.normpath(os.path.join(WorkspaceDir,Item[2])))) + for Item in DistPkg.ModuleSurfaceArea: + ContentFile.Pack(os.path.dirname(os.path.normpath(os.path.join(WorkspaceDir,Item[2])))) + + # Add tools files and information + if Options.ToolsDir: + ToolsFiles = MiscFileClass() + ToolsRoot = os.path.normpath(os.path.join(WorkspaceDir, Options.ToolsDir)) + ContentFile.Pack(ToolsRoot) + ToolsFileList = GetFiles(ToolsRoot, ['CVS', '.svn']) + for Item in ToolsFileList: + OriPath = Item[len(WorkspaceDir)+1:] + FileObj = FileClass() + FileObj.Filename = OriPath + (Name, Ext) = os.path.splitext(OriPath) + if Ext.upper() in ['EXE', 'COM', 'EFI']: + FileObj.Executable = 'True' + ToolsFiles.Files.append(FileObj) + DistPkg.Tools = ToolsFiles + + # Add misc files and information + if Options.MiscFiles: + MiscFiles = MiscFileClass() + for Item in Options.MiscFiles: + ContentFile.PackFile(Item) + FileObj = FileClass() + FileObj.Filename = Item + (Name, Ext) = os.path.splitext(Item) + if Ext.upper() in ['EXE', 'COM', 'EFI']: + FileObj.Executable = 'True' + MiscFiles.Files.append(FileObj) + DistPkg.MiscellaneousFiles = MiscFiles + + print "Compressing Distribution Package File ..." + ContentFile.Close() + + # Add temp distribution header + if Options.TemplateFile: + TempXML = DistributionPackageXml() + DistPkg.Header = TempXML.FromXml(Options.TemplateFile).Header + # Add init dp information + else: + DistPkg.Header.Name = 'Distribution Package' + DistPkg.Header.Guid = str(uuid.uuid4()) + DistPkg.Header.Version = '1.0' + + # Add Md5Sigature + Md5Sigature = md5.new(open(str(ContentFile)).read()) + DistPkg.Header.Signature = Md5Sigature.hexdigest() + # Add current Date + DistPkg.Header.Date = str(time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())) + + # Finish final dp file + DistPkgFile = PackageFile(Options.DistributionFile, "w") + DistPkgFile.PackFile(str(ContentFile)) + DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), "dist.pkg") + DistPkgFile.Close() + print "DONE" + + 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( + "\nMkPkg", + CODE_ERROR, + "Unknown fatal error when creating [%s]" % Options.DistributionFile, + ExtraData="\n(Please send email to dev@buildtools.tianocore.org 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: + Progressor.Abort() + +if __name__ == '__main__': + sys.exit(Main()) + diff --git a/BaseTools/Source/Python/PackagingTool/PackageFile.py b/BaseTools/Source/Python/PackagingTool/PackageFile.py new file mode 100644 index 0000000000..12544927c9 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/PackageFile.py @@ -0,0 +1,160 @@ +## @file +# +# PackageFile class represents the zip file of a 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 zipfile +import tempfile + +from Common import EdkLogger +from Common.Misc import * +from Common.BuildToolError import * + +class PackageFile: + def __init__(self, FileName, Mode="r"): + self._FileName = FileName + if Mode not in ["r", "w", "a"]: + Mode = "r" + try: + self._ZipFile = zipfile.ZipFile(FileName, Mode, zipfile.ZIP_DEFLATED) + self._Files = {} + for F in self._ZipFile.namelist(): + self._Files[os.path.normpath(F)] = F + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_OPEN_FAILURE, + ExtraData="%s (%s)" % (FileName, str(X))) + + BadFile = self._ZipFile.testzip() + if BadFile != None: + EdkLogger.error("PackagingTool", FILE_CHECKSUM_FAILURE, + ExtraData="[%s] in %s" % (BadFile, FileName)) + + def __str__(self): + return self._FileName + + def Unpack(self, To): + for F in self._ZipFile.namelist(): + ToFile = os.path.normpath(os.path.join(To, F)) + print F, "->", ToFile + self.Extract(F, ToFile) + + def UnpackFile(self, File, ToFile): + File = File.replace('\\', '/') + if File in self._ZipFile.namelist(): + print File, "->", ToFile + self.Extract(File, ToFile) + + return ToFile + + return '' + + def Extract(self, Which, To): + Which = os.path.normpath(Which) + if Which not in self._Files: + EdkLogger.error("PackagingTool", FILE_NOT_FOUND, + ExtraData="[%s] in %s" % (Which, self._FileName)) + try: + FileContent = self._ZipFile.read(self._Files[Which]) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_DECOMPRESS_FAILURE, + ExtraData="[%s] in %s (%s)" % (Which, self._FileName, str(X))) + try: + CreateDirectory(os.path.dirname(To)) + ToFile = open(To, "wb") + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_OPEN_FAILURE, + ExtraData="%s (%s)" % (To, str(X))) + + try: + ToFile.write(FileContent) + ToFile.close() + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_WRITE_FAILURE, + ExtraData="%s (%s)" % (To, str(X))) + + def Remove(self, Files): + TmpDir = os.path.join(tempfile.gettempdir(), ".packaging") + if os.path.exists(TmpDir): + RemoveDirectory(TmpDir, True) + + os.mkdir(TmpDir) + self.Unpack(TmpDir) + for F in Files: + F = os.path.normpath(F) + if F not in self._Files: + EdkLogger.error("PackagingTool", FILE_NOT_FOUND, + ExtraData="%s is not in %s!" % (F, self._FileName)) + #os.remove(os.path.join(TmpDir, F)) # no need to really remove file + self._Files.pop(F) + self._ZipFile.close() + + self._ZipFile = zipfile.ZipFile(self._FileName, "w", zipfile.ZIP_DEFLATED) + Cwd = os.getcwd() + os.chdir(TmpDir) + self.PackFiles(self._Files) + os.chdir(Cwd) + RemoveDirectory(TmpDir, True) + + def Pack(self, Top): + if not os.path.isdir(Top): + EdkLogger.error("PackagingTool", FILE_UNKNOWN_ERROR, "%s is not a directory!" %Top) + + FilesToPack = [] + ParentDir = os.path.dirname(Top) + BaseDir = os.path.basename(Top) + Cwd = os.getcwd() + os.chdir(ParentDir) + for Root, Dirs, Files in os.walk(BaseDir): + if 'CVS' in Dirs: + Dirs.remove('CVS') + if '.svn' in Dirs: + Dirs.remove('.svn') + for F in Files: + FilesToPack.append(os.path.join(Root, F)) + self.PackFiles(FilesToPack) + os.chdir(Cwd) + + def PackFiles(self, Files): + for F in Files: + try: + print "packing ...", F + self._ZipFile.write(F) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (F, str(X))) + + def PackFile(self, File, ArcName=None): + try: + print "packing ...", File + self._ZipFile.write(File, ArcName) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (File, str(X))) + + def PackData(self, Data, ArcName): + try: + self._ZipFile.writestr(ArcName, Data) + except BaseException, X: + EdkLogger.error("PackagingTool", FILE_COMPRESS_FAILURE, + ExtraData="%s (%s)" % (ArcName, str(X))) + + def Close(self): + self._ZipFile.close() + +if __name__ == '__main__': + pass + diff --git a/BaseTools/Source/Python/PackagingTool/RmPkg.py b/BaseTools/Source/Python/PackagingTool/RmPkg.py new file mode 100644 index 0000000000..e7eedd0776 --- /dev/null +++ b/BaseTools/Source/Python/PackagingTool/RmPkg.py @@ -0,0 +1,218 @@ +## @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 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 IpiDb import * +from DependencyRules import * + +# 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/ 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("RmPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", + ExtraData="WORKSPACE") + + WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"]) + if not os.path.exists(WorkspaceDir): + EdkLogger.error("RmPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) + elif ' ' in WorkspaceDir: + EdkLogger.error("RmPkg", 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 -g -n [-y] [-q | -v] [-h]" + + Parser = OptionParser(description=__copyright__,version=__version__,prog="RmPkg",usage=UsageString) + + Parser.add_option("-?", action="help", help="show this help message and exit") + +# Parser.add_option("-f", "--force", action="store_true", type=None, dest="ForceRemove", +# help="Force creation - overwrite existing one.") + + Parser.add_option("-y", "--yes", action="store_true", dest="Yes", + help="Not asking for confirmation when deleting files.") + + Parser.add_option("-n", "--package-version", action="store", type="string", dest="PackageVersion", + help="The version of distribution package to be removed.") + + Parser.add_option("-g", "--package-guid", action="store", type="string", dest="PackageGuid", + help="The GUID of distribution package to be removed.") + + 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 + +## Remove all empty dirs under the path +def RemoveEmptyDirs(Path): + # Remove all sub dirs + for Root, Dirs, Files in os.walk(Path): + for Dir in Dirs: + FullPath = os.path.normpath(os.path.join(Root, Dir)) + if os.path.isdir(FullPath): + if os.listdir(FullPath) == []: + os.rmdir(FullPath) + else: + RemoveEmptyDirs(FullPath) + # Remove itself + if os.path.isdir(Path) and os.listdir(Path) == []: + os.rmdir(Path) + + +## 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 = MyOptionParser() + try: + if not Options.PackageGuid and not Options.PackageVersion: + EdkLogger.error("RmPkg", OPTION_MISSING, ExtraData="The GUID and Version of distribution package must be specified") + + if Options.LogLevel < EdkLogger.DEBUG_9: + EdkLogger.SetLevel(Options.LogLevel + 1) + else: + EdkLogger.SetLevel(Options.LogLevel) + + CheckEnvVariable() + WorkspaceDir = os.environ["WORKSPACE"] + + # Prepare check dependency + Db = IpiDatabase(os.path.normpath(os.path.join(WorkspaceDir, "Conf/DistributionPackageDatabase.db"))) + Db.InitDatabase() + Dep = DependencyRules(Db) + + Guid = Options.PackageGuid + Version = Options.PackageVersion + + # Check Dp existing + if not Dep.CheckDpExists(Guid, Version): + EdkLogger.error("RmPkg", UNKNOWN_ERROR, "This distribution package are not installed!") + + # Check Dp depex + if not Dep.CheckDpDepexForRemove(Guid, Version): + print "Some packages/modules are depending on this distribution package, do you really want to remove it?" + print "Press Y to delete all files or press other keys to quit:" + Input = Input = sys.stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + EdkLogger.error("RmPkg", UNKNOWN_ERROR, "User interrupt") + + # Remove all files + if not Options.Yes: + print "All files of the distribution package will be removed, do you want to continue?" + print "Press Y to remove all files or press other keys to quit:" + Input = Input = sys.stdin.readline() + Input = Input.replace('\r', '').replace('\n', '') + if Input.upper() != 'Y': + EdkLogger.error("RmPkg", UNKNOWN_ERROR, "User interrupt") + + # Remove all files + MissingFileList = [] + for Item in Db.GetDpFileList(Guid, Version): + if os.path.isfile(Item): + print "Removing file [%s] ..." % Item + os.remove(Item) + else: + MissingFileList.append(Item) + + # Remove all empty dirs of package + for Item in Db.GetPackageListFromDp(Guid, Version): + Dir = os.path.dirname(Item[2]) + RemoveEmptyDirs(Dir) + + # Remove all empty dirs of module + for Item in Db.GetStandaloneModuleInstallPathListFromDp(Guid, Version): + Dir = os.path.dirname(Item) + RemoveEmptyDirs(Dir) + + # update database + EdkLogger.quiet("Update Distribution Package Database ...") + Db.RemoveDpObj(Guid, Version) + EdkLogger.quiet("DONE") + + 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( + "\nRmPkg", + CODE_ERROR, + "Unknown fatal error when removing package", + ExtraData="\n(Please send email to dev@buildtools.tianocore.org 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: + Progressor.Abort() + +if __name__ == '__main__': + sys.exit(Main()) -- cgit v1.2.3