]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Core/PackageFile.py
BaseTools: Replace BSD License with BSD+Patent License
[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 - 2018, Intel Corporation. All rights reserved.<BR>
6 #
7 # SPDX-License-Identifier: BSD-2-Clause-Patent
8 #
9
10 '''
11 PackageFile
12 '''
13
14 ##
15 # Import Modules
16 #
17 import os.path
18 import zipfile
19 import tempfile
20 import platform
21
22 from Logger.ToolError import FILE_OPEN_FAILURE
23 from Logger.ToolError import FILE_CHECKSUM_FAILURE
24 from Logger.ToolError import FILE_NOT_FOUND
25 from Logger.ToolError import FILE_DECOMPRESS_FAILURE
26 from Logger.ToolError import FILE_UNKNOWN_ERROR
27 from Logger.ToolError import FILE_WRITE_FAILURE
28 from Logger.ToolError import FILE_COMPRESS_FAILURE
29 import Logger.Log as Logger
30 from Logger import StringTable as ST
31 from Library.Misc import CreateDirectory
32 from Library.Misc import RemoveDirectory
33 from Core.FileHook import __FileHookOpen__
34 from Common.MultipleWorkspace import MultipleWorkspace as mws
35
36
37 class PackageFile:
38 def __init__(self, FileName, Mode="r"):
39 self._FileName = FileName
40 if Mode not in ["r", "w", "a"]:
41 Mode = "r"
42 try:
43 self._ZipFile = zipfile.ZipFile(FileName, Mode, \
44 zipfile.ZIP_DEFLATED)
45 self._Files = {}
46 for Filename in self._ZipFile.namelist():
47 self._Files[os.path.normpath(Filename)] = Filename
48 except BaseException as Xstr:
49 Logger.Error("PackagingTool", FILE_OPEN_FAILURE,
50 ExtraData="%s (%s)" % (FileName, str(Xstr)))
51
52 BadFile = self._ZipFile.testzip()
53 if BadFile is not None:
54 Logger.Error("PackagingTool", FILE_CHECKSUM_FAILURE,
55 ExtraData="[%s] in %s" % (BadFile, FileName))
56
57 def GetZipFile(self):
58 return self._ZipFile
59
60 ## Get file name
61 #
62 def __str__(self):
63 return self._FileName
64
65 ## Extract the file
66 #
67 # @param To: the destination file
68 #
69 def Unpack(self, ToDest):
70 for FileN in self._ZipFile.namelist():
71 ToFile = os.path.normpath(os.path.join(ToDest, FileN))
72 Msg = "%s -> %s" % (FileN, ToFile)
73 Logger.Info(Msg)
74 self.Extract(FileN, ToFile)
75
76 ## Extract the file
77 #
78 # @param File: the extracted file
79 # @param ToFile: the destination file
80 #
81 def UnpackFile(self, File, ToFile):
82 File = File.replace('\\', '/')
83 if File in self._ZipFile.namelist():
84 Msg = "%s -> %s" % (File, ToFile)
85 Logger.Info(Msg)
86 self.Extract(File, ToFile)
87 return ToFile
88
89 return ''
90
91 ## Extract the file
92 #
93 # @param Which: the source path
94 # @param ToDest: the destination path
95 #
96 def Extract(self, Which, ToDest):
97 Which = os.path.normpath(Which)
98 if Which not in self._Files:
99 Logger.Error("PackagingTool", FILE_NOT_FOUND,
100 ExtraData="[%s] in %s" % (Which, self._FileName))
101 try:
102 FileContent = self._ZipFile.read(self._Files[Which])
103 except BaseException as Xstr:
104 Logger.Error("PackagingTool", FILE_DECOMPRESS_FAILURE,
105 ExtraData="[%s] in %s (%s)" % (Which, \
106 self._FileName, \
107 str(Xstr)))
108 try:
109 CreateDirectory(os.path.dirname(ToDest))
110 if os.path.exists(ToDest) and not os.access(ToDest, os.W_OK):
111 Logger.Warn("PackagingTool", \
112 ST.WRN_FILE_NOT_OVERWRITTEN % ToDest)
113 return
114 else:
115 ToFile = __FileHookOpen__(ToDest, 'wb')
116 except BaseException as Xstr:
117 Logger.Error("PackagingTool", FILE_OPEN_FAILURE,
118 ExtraData="%s (%s)" % (ToDest, str(Xstr)))
119
120 try:
121 ToFile.write(FileContent)
122 ToFile.close()
123 except BaseException as Xstr:
124 Logger.Error("PackagingTool", FILE_WRITE_FAILURE,
125 ExtraData="%s (%s)" % (ToDest, str(Xstr)))
126
127 ## Remove the file
128 #
129 # @param Files: the removed files
130 #
131 def Remove(self, Files):
132 TmpDir = os.path.join(tempfile.gettempdir(), ".packaging")
133 if os.path.exists(TmpDir):
134 RemoveDirectory(TmpDir, True)
135
136 os.mkdir(TmpDir)
137 self.Unpack(TmpDir)
138 for SinF in Files:
139 SinF = os.path.normpath(SinF)
140 if SinF not in self._Files:
141 Logger.Error("PackagingTool", FILE_NOT_FOUND,
142 ExtraData="%s is not in %s!" % \
143 (SinF, self._FileName))
144 self._Files.pop(SinF)
145 self._ZipFile.close()
146
147 self._ZipFile = zipfile.ZipFile(self._FileName, "w", \
148 zipfile.ZIP_DEFLATED)
149 Cwd = os.getcwd()
150 os.chdir(TmpDir)
151 self.PackFiles(self._Files)
152 os.chdir(Cwd)
153 RemoveDirectory(TmpDir, True)
154
155 ## Pack the files under Top directory, the directory shown in the zipFile start from BaseDir,
156 # BaseDir should be the parent directory of the Top directory, for example,
157 # Pack(Workspace\Dir1, Workspace) will pack files under Dir1, and the path in the zipfile will
158 # start from Workspace
159 #
160 # @param Top: the top directory
161 # @param BaseDir: the base directory
162 #
163 def Pack(self, Top, BaseDir):
164 if not os.path.isdir(Top):
165 Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR, \
166 "%s is not a directory!" %Top)
167
168 FilesToPack = []
169 Cwd = os.getcwd()
170 os.chdir(BaseDir)
171 RelaDir = Top[Top.upper().find(BaseDir.upper()).\
172 join(len(BaseDir).join(1)):]
173
174 for Root, Dirs, Files in os.walk(RelaDir):
175 if 'CVS' in Dirs:
176 Dirs.remove('CVS')
177 if '.svn' in Dirs:
178 Dirs.remove('.svn')
179
180 for Dir in Dirs:
181 if Dir.startswith('.'):
182 Dirs.remove(Dir)
183 for File1 in Files:
184 if File1.startswith('.'):
185 continue
186 ExtName = os.path.splitext(File1)[1]
187 #
188 # skip '.dec', '.inf', '.dsc', '.fdf' files
189 #
190 if ExtName.lower() in ['.dec', '.inf', '.dsc', '.fdf']:
191 continue
192 FilesToPack.append(os.path.join(Root, File1))
193 self.PackFiles(FilesToPack)
194 os.chdir(Cwd)
195
196 ## Pack the file
197 #
198 # @param Files: the files to pack
199 #
200 def PackFiles(self, Files):
201 for File in Files:
202 Cwd = os.getcwd()
203 os.chdir(mws.getWs(mws.WORKSPACE, File))
204 self.PackFile(File)
205 os.chdir(Cwd)
206
207 ## Pack the file
208 #
209 # @param File: the files to pack
210 # @param ArcName: the Arc Name
211 #
212 def PackFile(self, File, ArcName=None):
213 try:
214 #
215 # avoid packing same file multiple times
216 #
217 if platform.system() != 'Windows':
218 File = File.replace('\\', '/')
219 ZipedFilesNameList = self._ZipFile.namelist()
220 for ZipedFile in ZipedFilesNameList:
221 if File == os.path.normpath(ZipedFile):
222 return
223 Logger.Info("packing ..." + File)
224 self._ZipFile.write(File, ArcName)
225 except BaseException as Xstr:
226 Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE,
227 ExtraData="%s (%s)" % (File, str(Xstr)))
228
229 ## Write data to the packed file
230 #
231 # @param Data: data to write
232 # @param ArcName: the Arc Name
233 #
234 def PackData(self, Data, ArcName):
235 try:
236 if os.path.splitext(ArcName)[1].lower() == '.pkg':
237 Data = Data.encode('utf_8')
238 self._ZipFile.writestr(ArcName, Data)
239 except BaseException as Xstr:
240 Logger.Error("PackagingTool", FILE_COMPRESS_FAILURE,
241 ExtraData="%s (%s)" % (ArcName, str(Xstr)))
242
243 ## Close file
244 #
245 #
246 def Close(self):
247 self._ZipFile.close()
248
249
250