audk/BaseTools/Source/Python/UPT/MkPkg.py

280 lines
10 KiB
Python

## @file
# Install distribution package.
#
# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
#
# 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.
#
'''
MkPkg
'''
##
# Import Modules
#
from os import remove
from os import getcwd
from os import chdir
import os.path
from sys import stdin
from sys import platform
from traceback import format_exc
from platform import python_version
import md5
from time import strftime
from time import localtime
from uuid import uuid4
from Logger import StringTable as ST
from Logger.ToolError import OPTION_UNKNOWN_ERROR
from Logger.ToolError import OPTION_VALUE_INVALID
from Logger.ToolError import ABORT_ERROR
from Logger.ToolError import UPT_REPKG_ERROR
from Logger.ToolError import CODE_ERROR
from Logger.ToolError import FatalError
from Logger.ToolError import FILE_NOT_FOUND
import Logger.Log as Logger
from Xml.XmlParser import DistributionPackageXml
from Xml.IniToXml import IniToXml
from Library import GlobalData
from Library.ParserValidate import IsValidPath
from Core.DistributionPackageClass import DistributionPackageClass
from Core.PackageFile import PackageFile
## CheckForExistingDp
#
# Check if there is a same name DP file existing
# @param Path: The path to be checked
#
def CheckForExistingDp(Path):
if os.path.exists(Path):
Logger.Info(ST.MSG_DISTRIBUTION_PACKAGE_FILE_EXISTS % Path)
Input = stdin.readline()
Input = Input.replace('\r', '').replace('\n', '')
if Input.upper() != "Y":
Logger.Error("\nMkPkg", ABORT_ERROR, ST.ERR_USER_ABORT, RaiseError=True)
## 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.
#
#
def Main(Options = None):
if Options == None:
Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND)
try:
DataBase = GlobalData.gDB
ContentFileClosed = True
WorkspaceDir = GlobalData.gWORKSPACE
#
# Init PackFileToCreate
#
if not Options.PackFileToCreate:
Logger.Error("\nMkPkg", OPTION_UNKNOWN_ERROR, ST.ERR_OPTION_NOT_FOUND)
#
# Handle if the distribution package file already exists
#
CheckForExistingDp(Options.PackFileToCreate)
#
# Check package file existing and valid
#
CheckFileList('.DEC', Options.PackageFileList, ST.ERR_INVALID_PACKAGE_NAME, ST.ERR_INVALID_PACKAGE_PATH)
#
# Check module file existing and valid
#
CheckFileList('.INF', Options.ModuleFileList, ST.ERR_INVALID_MODULE_NAME, ST.ERR_INVALID_MODULE_PATH)
#
# Get list of files that installed with RePackage attribute available
#
RePkgDict = DataBase.GetRePkgDict()
ContentFile = PackageFile(GlobalData.gCONTENT_FILE, "w")
ContentFileClosed = False
#
# Add temp distribution header
#
if Options.PackageInformationDataFile:
XmlFile = IniToXml(Options.PackageInformationDataFile)
DistPkg = DistributionPackageXml().FromXml(XmlFile)
remove(XmlFile)
#
# add distribution level tool/misc files
# before pack, current dir should be workspace dir, else the full
# path will be in the pack file
#
Cwd = getcwd()
chdir(WorkspaceDir)
ToolObject = DistPkg.Tools
MiscObject = DistPkg.MiscellaneousFiles
FileList = []
if ToolObject:
FileList += ToolObject.GetFileList()
if MiscObject:
FileList += MiscObject.GetFileList()
for FileObject in FileList:
#
# If you have unicode file names, please convert them to byte
# strings in your desired encoding before passing them to
# write().
#
FromFile = os.path.normpath(FileObject.GetURI()).encode('utf_8')
FileFullPath = os.path.normpath(os.path.join(WorkspaceDir, FromFile))
if FileFullPath in RePkgDict:
(DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath]
if not Repackage:
Logger.Error("\nMkPkg",
UPT_REPKG_ERROR,
ST.ERR_UPT_REPKG_ERROR,
ExtraData=ST.MSG_REPKG_CONFLICT %\
(FileFullPath, DpGuid, DpVersion, DpName)
)
else:
DistPkg.Header.RePackage = True
ContentFile.PackFile(FromFile)
chdir(Cwd)
#
# Add init dp information
#
else:
DistPkg = DistributionPackageClass()
DistPkg.Header.Name = 'Distribution Package'
DistPkg.Header.Guid = str(uuid4())
DistPkg.Header.Version = '1.0'
DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, \
Options.ModuleFileList)
FileList, MetaDataFileList = DistPkg.GetDistributionFileList()
for File in FileList + MetaDataFileList:
FileFullPath = os.path.normpath(os.path.join(WorkspaceDir, File))
#
# check whether file was included in a distribution that can not
# be repackaged
#
if FileFullPath in RePkgDict:
(DpGuid, DpVersion, DpName, Repackage) = RePkgDict[FileFullPath]
if not Repackage:
Logger.Error("\nMkPkg",
UPT_REPKG_ERROR,
ST.ERR_UPT_REPKG_ERROR,
ExtraData = \
ST.MSG_REPKG_CONFLICT %(FileFullPath, DpName, \
DpGuid, DpVersion)
)
else:
DistPkg.Header.RePackage = True
Cwd = getcwd()
chdir(WorkspaceDir)
ContentFile.PackFiles(FileList)
chdir(Cwd)
Logger.Verbose(ST.MSG_COMPRESS_DISTRIBUTION_PKG)
ContentFile.Close()
ContentFileClosed = True
#
# Add Md5Sigature
#
DistPkg.Header.Signature = md5.new(open(str(ContentFile), 'rb').read()).hexdigest()
#
# Add current Date
#
DistPkg.Header.Date = str(strftime("%Y-%m-%dT%H:%M:%S", localtime()))
#
# Finish final dp file
#
DistPkgFile = PackageFile(Options.PackFileToCreate, "w")
DistPkgFile.PackFile(str(ContentFile))
DistPkgXml = DistributionPackageXml()
DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), GlobalData.gDESC_FILE)
DistPkgFile.Close()
Logger.Quiet(ST.MSG_FINISH)
ReturnCode = 0
except FatalError, XExcept:
ReturnCode = XExcept.args[0]
if Logger.GetLevel() <= Logger.DEBUG_9:
Logger.Quiet(ST.MSG_PYTHON_ON % \
(python_version(), platform) + format_exc())
except KeyboardInterrupt:
ReturnCode = ABORT_ERROR
if Logger.GetLevel() <= Logger.DEBUG_9:
Logger.Quiet(ST.MSG_PYTHON_ON % \
(python_version(), platform) + format_exc())
except OSError:
pass
except:
Logger.Error(
"\nMkPkg",
CODE_ERROR,
ST.ERR_UNKNOWN_FATAL_CREATING_ERR % \
Options.PackFileToCreate,
ExtraData=ST.MSG_SEARCH_FOR_HELP,
RaiseError=False
)
Logger.Quiet(ST.MSG_PYTHON_ON % \
(python_version(), platform) + format_exc())
ReturnCode = CODE_ERROR
finally:
if os.path.exists(GlobalData.gCONTENT_FILE):
if not ContentFileClosed:
ContentFile.Close()
os.remove(GlobalData.gCONTENT_FILE)
return ReturnCode
## CheckFileList
#
# @param QualifiedExt: QualifiedExt
# @param FileList: FileList
# @param ErrorStringExt: ErrorStringExt
# @param ErrorStringFullPath: ErrorStringFullPath
#
def CheckFileList(QualifiedExt, FileList, ErrorStringExt, ErrorStringFullPath):
if not FileList:
return
WorkspaceDir = GlobalData.gWORKSPACE
WorkspaceDir = os.path.normpath(WorkspaceDir)
for Item in FileList:
Ext = os.path.splitext(Item)[1]
if Ext.upper() != QualifiedExt.upper():
Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \
ErrorStringExt % Item)
Item = os.path.normpath(Item)
Path = os.path.normpath(os.path.join(WorkspaceDir, Item))
if not os.path.exists(Path):
Logger.Error("\nMkPkg", FILE_NOT_FOUND, ST.ERR_NOT_FOUND % Item)
elif Item == Path:
Logger.Error("\nMkPkg", OPTION_VALUE_INVALID,
ErrorStringFullPath % Item)
elif not IsValidPath(Item, WorkspaceDir):
Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \
ErrorStringExt % Item)
if not os.path.split(Item)[0]:
Logger.Error("\nMkPkg", OPTION_VALUE_INVALID, \
ST.ERR_INVALID_METAFILE_PATH % Item)