]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Core/PackageFile.py
ec6f5503eaad39756894c329f87432e763d17475
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Core / PackageFile.py
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 is not 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