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''' 17PackageFile 18''' 19 20## 21# Import Modules 22# 23import os.path 24import zipfile 25import tempfile 26import platform 27 28from Logger.ToolError import FILE_OPEN_FAILURE 29from Logger.ToolError import FILE_CHECKSUM_FAILURE 30from Logger.ToolError import FILE_NOT_FOUND 31from Logger.ToolError import FILE_DECOMPRESS_FAILURE 32from Logger.ToolError import FILE_UNKNOWN_ERROR 33from Logger.ToolError import FILE_WRITE_FAILURE 34from Logger.ToolError import FILE_COMPRESS_FAILURE 35import Logger.Log as Logger 36from Logger import StringTable as ST 37from Library.Misc import CreateDirectory 38from Library.Misc import RemoveDirectory 39from Core.FileHook import __FileHookOpen__ 40from Common.MultipleWorkspace import MultipleWorkspace as mws 41 42 43class 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