Home | History | Annotate | Download | only in Core
      1 ## @file

      2 #

      3 # PackageFile class represents the zip file of a distribution package.

      4 #

      5 # Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>

      6 #

      7 # This program and the accompanying materials are licensed and made available 

      8 # under the terms and conditions of the BSD License which accompanies this 

      9 # distribution. The full text of the license may be found at 

     10 # http://opensource.org/licenses/bsd-license.php

     11 #

     12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

     13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

     14 #

     15 
     16 '''
     17 PackageFile
     18 '''
     19 
     20 ##

     21 # Import Modules

     22 #

     23 import os.path
     24 import zipfile
     25 import tempfile
     26 import platform
     27 
     28 from Logger.ToolError import FILE_OPEN_FAILURE
     29 from Logger.ToolError import FILE_CHECKSUM_FAILURE
     30 from Logger.ToolError import FILE_NOT_FOUND
     31 from Logger.ToolError import FILE_DECOMPRESS_FAILURE
     32 from Logger.ToolError import FILE_UNKNOWN_ERROR
     33 from Logger.ToolError import FILE_WRITE_FAILURE
     34 from Logger.ToolError import FILE_COMPRESS_FAILURE
     35 import Logger.Log as Logger
     36 from Logger import StringTable as ST
     37 from Library.Misc import CreateDirectory
     38 from Library.Misc import RemoveDirectory
     39 from Core.FileHook import __FileHookOpen__
     40 from Common.MultipleWorkspace import MultipleWorkspace as mws
     41 
     42 
     43 class PackageFile:
     44     def __init__(self, FileName, Mode="r"):
     45         self._FileName = FileName
     46         if Mode not in ["r", "w", "a"]:
     47             Mode = "r"
     48         try:
     49             self._ZipFile = zipfile.ZipFile(FileName, Mode, \
     50                                             zipfile.ZIP_DEFLATED)
     51             self._Files = {}
     52             for Filename in self._ZipFile.namelist():
     53                 self._Files[os.path.normpath(Filename)] = Filename
     54         except BaseException, Xstr:
     55             Logger.Error("PackagingTool", FILE_OPEN_FAILURE, 
     56                             ExtraData="%s (%s)" % (FileName, str(Xstr)))
     57 
     58         BadFile = self._ZipFile.testzip()
     59         if BadFile != None:
     60             Logger.Error("PackagingTool", FILE_CHECKSUM_FAILURE, 
     61                             ExtraData="[%s] in %s" % (BadFile, FileName))
     62     
     63     def GetZipFile(self):
     64         return self._ZipFile
     65     
     66     ## Get file name 

     67     #

     68     def __str__(self):
     69         return self._FileName
     70     
     71     ## Extract the file

     72     # 

     73     # @param To:  the destination file 

     74     #

     75     def Unpack(self, ToDest):
     76         for FileN in self._ZipFile.namelist():
     77             ToFile = os.path.normpath(os.path.join(ToDest, FileN))
     78             Msg = "%s -> %s" % (FileN, ToFile)
     79             Logger.Info(Msg)
     80             self.Extract(FileN, ToFile)
     81     
     82     ## Extract the file

     83     # 

     84     # @param File:  the extracted file 

     85     # @param ToFile:  the destination file 

     86     #

     87     def UnpackFile(self, File, ToFile):
     88         File = File.replace('\\', '/')
     89         if File in self._ZipFile.namelist():
     90             Msg = "%s -> %s" % (File, ToFile)
     91             Logger.Info(Msg)
     92             self.Extract(File, ToFile)
     93             return ToFile
     94         
     95         return ''
     96     
     97     ## Extract the file
     98     # 
     99     # @param Which:  the source path 
    100     # @param ToDest:  the destination path 
    101     #
    102     def Extract(self, Which, ToDest):
    103         Which = os.path.normpath(Which)
    104         if Which not in self._Files:
    105             Logger.Error("PackagingTool", FILE_NOT_FOUND,
    106                             ExtraData="[%s] in %s" % (Which, self._FileName))
    107         try:
    108             FileContent = self._ZipFile.read(self._Files[Which])
    109         except BaseException, Xstr:
    110             Logger.Error("PackagingTool", FILE_DECOMPRESS_FAILURE, 
    111                             ExtraData="[%s] in %s (%s)" % (Which, \
    112                                                            self._FileName, \
    113                                                            str(Xstr)))
    114         try:
    115             CreateDirectory(os.path.dirname(ToDest))
    116             if os.path.exists(ToDest) and not os.access(ToDest, os.W_OK):
    117                 Logger.Warn("PackagingTool", \
    118                             ST.WRN_FILE_NOT_OVERWRITTEN % ToDest)
    119                 return
    120             else:
    121                 ToFile = __FileHookOpen__(ToDest, 'wb')
    122         except BaseException, Xstr:
    123             Logger.Error("PackagingTool", FILE_OPEN_FAILURE, 
    124                             ExtraData="%s (%s)" % (ToDest, str(Xstr)))
    125 
    126         try:
    127             ToFile.write(FileContent)
    128             ToFile.close()
    129         except BaseException, Xstr:
    130             Logger.Error("PackagingTool", FILE_WRITE_FAILURE, 
    131                             ExtraData="%s (%s)" % (ToDest, str(Xstr)))
    132 
    133     ## Remove the file
    134     # 
    135     # @param Files:  the removed files 
    136     #
    137     def Remove(self, Files):
    138         TmpDir = os.path.join(tempfile.gettempdir(), ".packaging")
    139         if os.path.exists(TmpDir):
    140             RemoveDirectory(TmpDir, True)
    141 
    142         os.mkdir(TmpDir)
    143         self.Unpack(TmpDir)
    144         for SinF in Files:
    145             SinF = os.path.normpath(SinF)
    146             if SinF not in self._Files:
    147                 Logger.Error("PackagingTool", FILE_NOT_FOUND, 
    148                                 ExtraData="%s is not in %s!" % \
    149                                 (SinF, self._FileName))
    150             self._Files.pop(SinF)
    151         self._ZipFile.close()
    152 
    153         self._ZipFile = zipfile.ZipFile(self._FileName, "w", \
    154                                         zipfile.ZIP_DEFLATED)
    155         Cwd = os.getcwd()
    156         os.chdir(TmpDir)
    157         self.PackFiles(self._Files)
    158         os.chdir(Cwd)
    159         RemoveDirectory(TmpDir, True)
    160 
    161     ## Pack the files under Top directory, the directory shown in the zipFile start from BaseDir,
    162     # BaseDir should be the parent directory of the Top directory, for example, 
    163     # Pack(Workspace\Dir1, Workspace) will pack files under Dir1, and the path in the zipfile will 
    164     # start from Workspace
    165     # 
    166     # @param Top:  the top directory 
    167     # @param BaseDir:  the base directory 
    168     #
    169     def Pack(self, Top, BaseDir):
    170         if not os.path.isdir(Top):
    171             Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR, \
    172                          "%s is not a directory!" %Top)
    173 
    174         FilesToPack = []
    175         Cwd = os.getcwd()
    176         os.chdir(BaseDir)
    177         RelaDir = Top[Top.upper().find(BaseDir.upper()).\
    178                       join(len(BaseDir).join(1)):] 
    179 
    180         for Root, Dirs, Files in os.walk(RelaDir):
    181             if 'CVS' in Dirs:
    182                 Dirs.remove('CVS')
    183             if '.svn' in Dirs:
    184                 Dirs.remove('.svn')
    185             
    186             for Dir in Dirs:
    187                 if Dir.startswith('.'):
    188                     Dirs.remove(Dir)
    189             for File1 in Files:
    190                 if File1.startswith('.'):
    191                     continue
    192                 ExtName = os.path.splitext(File1)[1]
    193                 #
    194                 # skip '.dec', '.inf', '.dsc', '.fdf' files
    195                 #
    196                 if ExtName.lower() in ['.dec', '.inf', '.dsc', '.fdf']:
    197                     continue
    198                 FilesToPack.append(os.path.join(Root, File1))
    199         self.PackFiles(FilesToPack)
    200         os.chdir(Cwd)
    201 
    202     ## Pack the file
    203     # 
    204     # @param Files:  the files to pack 
    205     #
    206     def PackFiles(self, Files):
    207         for File in Files:
    208             Cwd = os.getcwd()
    209             os.chdir(mws.getWs(mws.WORKSPACE, File))
    210             self.PackFile(File)
    211             os.chdir(Cwd)
    212 
    213     ## Pack the file
    214     # 
    215     # @param File:  the files to pack 
    216     # @param ArcName:  the Arc Name 
    217     #
    218     def PackFile(self, File, ArcName=None):
    219         try:
    220             #
    221             # avoid packing same file multiple times
    222             #
    223             if platform.system() != 'Windows':
    224                 File = File.replace('\\', '/')            
    225             ZipedFilesNameList = self._ZipFile.namelist()
    226             for ZipedFile in ZipedFilesNameList:
    227                 if File == os.path.normpath(ZipedFile):
    228                     return
    229             Logger.Info("packing ..." + File)
    230             self._ZipFile.write(File, ArcName)
    231         except BaseException, Xstr:
    232             Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE,
    233                             ExtraData="%s (%s)" % (File, str(Xstr)))
    234 
    235     ## Write data to the packed file
    236     # 
    237     # @param Data:  data to write 
    238     # @param ArcName:  the Arc Name 
    239     #
    240     def PackData(self, Data, ArcName):
    241         try:
    242             if os.path.splitext(ArcName)[1].lower() == '.pkg':
    243                 Data = Data.encode('utf_8')
    244             self._ZipFile.writestr(ArcName, Data)
    245         except BaseException, Xstr:
    246             Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE,
    247                             ExtraData="%s (%s)" % (ArcName, str(Xstr)))
    248 
    249     ## Close file
    250     # 
    251     #
    252     def Close(self):
    253         self._ZipFile.close()
    254 
    255 
    256 
    257