]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/InstallPkg.py
Sync BaseTool trunk (version r2601) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / Python / UPT / InstallPkg.py
1 ## @file
2 # Install distribution package.
3 #
4 # Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
5 #
6 # This program and the accompanying materials are licensed and made available
7 # under the terms and conditions of the BSD License which accompanies this
8 # distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
10 #
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14 """
15 Install a distribution package
16 """
17 ##
18 # Import Modules
19 #
20 import os.path
21 from os import chmod
22 from os import SEEK_SET
23 from os import SEEK_END
24 import stat
25 import md5
26 from sys import stdin
27 from sys import platform
28 from shutil import rmtree
29 from shutil import copyfile
30 from traceback import format_exc
31 from platform import python_version
32
33 from Logger import StringTable as ST
34 from Logger.ToolError import UNKNOWN_ERROR
35 from Logger.ToolError import FILE_UNKNOWN_ERROR
36 from Logger.ToolError import OPTION_MISSING
37 from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR
38 from Logger.ToolError import FatalError
39 from Logger.ToolError import ABORT_ERROR
40 from Logger.ToolError import CODE_ERROR
41 from Logger.ToolError import FORMAT_INVALID
42 from Logger.ToolError import FILE_TYPE_MISMATCH
43 import Logger.Log as Logger
44
45 from Library.Misc import CheckEnvVariable
46 from Library.Misc import Sdict
47 from Library.Misc import ConvertPath
48 from Library.ParserValidate import IsValidInstallPath
49 from Xml.XmlParser import DistributionPackageXml
50 from GenMetaFile.GenDecFile import PackageToDec
51 from GenMetaFile.GenInfFile import ModuleToInf
52 from Core.PackageFile import PackageFile
53 from Core.PackageFile import FILE_NOT_FOUND
54 from Core.PackageFile import FILE_CHECKSUM_FAILURE
55 from Core.PackageFile import CreateDirectory
56 from Core.DependencyRules import DependencyRules
57 from Library import GlobalData
58
59 ## InstallNewPackage
60 #
61 # @param WorkspaceDir: Workspace Directory
62 # @param Path: Package Path
63 # @param CustomPath: whether need to customize path at first
64 #
65 def InstallNewPackage(WorkspaceDir, Path, CustomPath = False):
66 if os.path.isabs(Path):
67 Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%Path)
68 elif CustomPath:
69 Logger.Info(ST.MSG_NEW_PKG_PATH)
70 else:
71 Path = ConvertPath(Path)
72 Path = os.path.normpath(Path)
73 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path))
74 if os.path.exists(FullPath):
75 Logger.Info(ST.ERR_DIR_ALREADY_EXIST%FullPath)
76 else:
77 return Path
78
79 Input = stdin.readline()
80 Input = Input.replace('\r', '').replace('\n', '')
81 if Input == '':
82 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
83 Input = Input.replace('\r', '').replace('\n', '')
84 return InstallNewPackage(WorkspaceDir, Input, False)
85
86
87 ## InstallNewModule
88 #
89 # @param WorkspaceDir: Workspace Directory
90 # @param Path: Standalone Module Path
91 # @param PathList: The already installed standalone module Path list
92 #
93 def InstallNewModule(WorkspaceDir, Path, PathList = None):
94 if PathList == None:
95 PathList = []
96 Path = ConvertPath(Path)
97 Path = os.path.normpath(Path)
98 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path))
99 if os.path.exists(FullPath) and FullPath not in PathList:
100 Logger.Info(ST.ERR_DIR_ALREADY_EXIST%Path)
101 elif Path == FullPath:
102 Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%FullPath)
103 else:
104 return Path
105
106 Input = stdin.readline()
107 Input = Input.replace('\r', '').replace('\n', '')
108 if Input == '':
109 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
110 Input = Input.replace('\r', '').replace('\n', '')
111 return InstallNewModule(WorkspaceDir, Input, PathList)
112
113
114 ## InstallNewFile
115 #
116 # @param WorkspaceDir: Workspace Direction
117 # @param File: File
118 #
119 def InstallNewFile(WorkspaceDir, File):
120 FullPath = os.path.normpath(os.path.join(WorkspaceDir, File))
121 if os.path.exists(FullPath):
122 Logger.Info(ST.ERR_FILE_ALREADY_EXIST %File)
123 Input = stdin.readline()
124 Input = Input.replace('\r', '').replace('\n', '')
125 if Input == '':
126 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
127 Input = Input.replace('\r', '').replace('\n', '')
128 return InstallNewFile(WorkspaceDir, Input)
129 else:
130 return File
131
132 ## UnZipDp
133 #
134 # UnZipDp
135 #
136 def UnZipDp(WorkspaceDir, Options, DataBase):
137 ContentZipFile = None
138 Logger.Quiet(ST.MSG_UZIP_PARSE_XML)
139 DpPkgFileName = Options.PackageFile
140 DistFile = PackageFile(DpPkgFileName)
141
142 DpDescFileName, ContentFileName = GetDPFile(DistFile.GetZipFile())
143
144 GlobalData.gUNPACK_DIR = os.path.normpath(os.path.join(WorkspaceDir, ".tmp"))
145 DistPkgFile = DistFile.UnpackFile(DpDescFileName,
146 os.path.normpath(os.path.join(GlobalData.gUNPACK_DIR, DpDescFileName)))
147 if not DistPkgFile:
148 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_FILE_BROKEN %DpDescFileName)
149
150 #
151 # Generate distpkg
152 #
153 DistPkgObj = DistributionPackageXml()
154 DistPkg = DistPkgObj.FromXml(DistPkgFile)
155 if DistPkg.Header.RePackage == '':
156 DistPkg.Header.RePackage = False
157 if DistPkg.Header.ReadOnly == '':
158 DistPkg.Header.ReadOnly = False
159
160 #
161 # prepare check dependency
162 #
163 Dep = DependencyRules(DataBase)
164 #
165 # Check distribution package installed or not
166 #
167 if Dep.CheckDpExists(DistPkg.Header.GetGuid(),
168 DistPkg.Header.GetVersion()):
169 Logger.Error("InstallPkg", UPT_ALREADY_INSTALLED_ERROR,
170 ST.WRN_DIST_PKG_INSTALLED)
171 #
172 # Check distribution dependency (all module dependency should be
173 # satisfied)
174 #
175 if not Dep.CheckDpDepexSatisfied(DistPkg):
176 Logger.Error("InstallPkg", UNKNOWN_ERROR,
177 ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY,
178 ExtraData=DistPkg.Header.Name)
179 #
180 # unzip contents.zip file
181 #
182 ContentFile = DistFile.UnpackFile(ContentFileName,
183 os.path.normpath(os.path.join(GlobalData.gUNPACK_DIR, ContentFileName)))
184 if not ContentFile:
185 Logger.Error("InstallPkg", FILE_NOT_FOUND,
186 ST.ERR_FILE_BROKEN % ContentFileName)
187
188 FilePointer = open(ContentFile, "rb")
189 #
190 # Assume no archive comment.
191 #
192 FilePointer.seek(0, SEEK_SET)
193 FilePointer.seek(0, SEEK_END)
194 #
195 # Get file size
196 #
197 FileSize = FilePointer.tell()
198 FilePointer.close()
199
200 if FileSize != 0:
201 ContentZipFile = PackageFile(ContentFile)
202
203 #
204 # verify MD5 signature when existed
205 #
206 if DistPkg.Header.Signature != '':
207 Md5Sigature = md5.new(open(ContentFile, 'rb').read())
208 if DistPkg.Header.Signature != Md5Sigature.hexdigest():
209 ContentZipFile.Close()
210 Logger.Error("InstallPkg", FILE_CHECKSUM_FAILURE,
211 ExtraData=ContentFile)
212
213 return DistPkg, Dep, ContentZipFile, DpPkgFileName
214
215 ## GetPackageList
216 #
217 # GetPackageList
218 #
219 def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleList, PackageList):
220 NewDict = Sdict()
221 for Guid, Version, Path in DistPkg.PackageSurfaceArea:
222 PackagePath = Path
223 Package = DistPkg.PackageSurfaceArea[Guid, Version, Path]
224 Logger.Info(ST.MSG_INSTALL_PACKAGE % Package.GetName())
225 if Dep.CheckPackageExists(Guid, Version):
226 Logger.Info(ST.WRN_PACKAGE_EXISTED %(Guid, Version))
227 NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath, Options.CustomPath)
228 InstallPackageContent(PackagePath, NewPackagePath, Package, ContentZipFile, Dep, WorkspaceDir, ModuleList,
229 DistPkg.Header.ReadOnly)
230 PackageList.append(Package)
231
232 NewDict[Guid, Version, Package.GetPackagePath()] = Package
233
234 #
235 # Now generate meta-data files, first generate all dec for package
236 # dec should be generated before inf, and inf should be generated after
237 # all packages installed, else hard to resolve modules' package
238 # dependency (Hard to get the location of the newly installed package)
239 #
240 for Package in PackageList:
241 FilePath = PackageToDec(Package)
242 Md5Sigature = md5.new(open(str(FilePath), 'rb').read())
243 Md5Sum = Md5Sigature.hexdigest()
244 if (FilePath, Md5Sum) not in Package.FileList:
245 Package.FileList.append((FilePath, Md5Sum))
246
247 return NewDict
248
249 ## GetModuleList
250 #
251 # GetModuleList
252 #
253 def GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList):
254 #
255 # ModulePathList will keep track of the standalone module path that
256 # we just installed. If a new module's path in that list
257 # (only multiple INF in one directory will be so), we will
258 # install them directly. If not, we will try to create a new directory
259 # for it.
260 #
261 ModulePathList = []
262
263 #
264 # Check module exist and install
265 #
266 Module = None
267 NewDict = Sdict()
268 for Guid, Version, Name, Path in DistPkg.ModuleSurfaceArea:
269 ModulePath = Path
270 Module = DistPkg.ModuleSurfaceArea[Guid, Version, Name, Path]
271 Logger.Info(ST.MSG_INSTALL_MODULE % Module.GetName())
272 if Dep.CheckModuleExists(Guid, Version, Name, Path):
273 Logger.Quiet(ST.WRN_MODULE_EXISTED %Path)
274 #
275 # here check for the multiple inf share the same module path cases:
276 # they should be installed into the same directory
277 #
278 ModuleFullPath = \
279 os.path.normpath(os.path.join(WorkspaceDir, ModulePath))
280 if ModuleFullPath not in ModulePathList:
281 NewModulePath = InstallNewModule(WorkspaceDir, ModulePath, ModulePathList)
282 NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath))
283 ModulePathList.append(NewModuleFullPath)
284 else:
285 NewModulePath = ModulePath
286
287 InstallModuleContent(ModulePath, NewModulePath, '', Module, ContentZipFile, WorkspaceDir, ModuleList, None,
288 DistPkg.Header.ReadOnly)
289 #
290 # Update module
291 #
292 Module.SetModulePath(Module.GetModulePath().replace(Path, NewModulePath, 1))
293
294 NewDict[Guid, Version, Name, Module.GetModulePath()] = Module
295
296 #
297 # generate all inf for modules
298 #
299 for (Module, Package) in ModuleList:
300 FilePath = ModuleToInf(Module)
301 Md5Sigature = md5.new(open(str(FilePath), 'rb').read())
302 Md5Sum = Md5Sigature.hexdigest()
303 if Package:
304 if (FilePath, Md5Sum) not in Package.FileList:
305 Package.FileList.append((FilePath, Md5Sum))
306 else:
307 if (FilePath, Md5Sum) not in Module.FileList:
308 Module.FileList.append((FilePath, Md5Sum))
309
310 return NewDict
311
312 ## GenToolMisc
313 #
314 # GenToolMisc
315 #
316 #
317 def GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile):
318 ToolObject = DistPkg.Tools
319 MiscObject = DistPkg.MiscellaneousFiles
320 DistPkg.FileList = []
321 FileList = []
322 ToolFileNum = 0
323 FileNum = 0
324 RootDir = WorkspaceDir
325
326 #
327 # FileList stores both tools files and misc files
328 # Misc file list must be appended to FileList *AFTER* Tools file list
329 #
330 if ToolObject:
331 FileList += ToolObject.GetFileList()
332 ToolFileNum = len(ToolObject.GetFileList())
333 if 'EDK_TOOLS_PATH' in os.environ:
334 RootDir = os.environ['EDK_TOOLS_PATH']
335 if MiscObject:
336 FileList += MiscObject.GetFileList()
337 for FileObject in FileList:
338 FileNum += 1
339 if FileNum > ToolFileNum:
340 #
341 # Misc files, root should be changed to WORKSPACE
342 #
343 RootDir = WorkspaceDir
344 File = ConvertPath(FileObject.GetURI())
345 ToFile = os.path.normpath(os.path.join(RootDir, File))
346 if os.path.exists(ToFile):
347 Logger.Info( ST.WRN_FILE_EXISTED % ToFile )
348 #
349 # ask for user input the new file name
350 #
351 Logger.Info( ST.MSG_NEW_FILE_NAME)
352 Input = stdin.readline()
353 Input = Input.replace('\r', '').replace('\n', '')
354 OrigPath = os.path.split(ToFile)[0]
355 ToFile = os.path.normpath(os.path.join(OrigPath, Input))
356 FromFile = os.path.join(FileObject.GetURI())
357 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, DistPkg.Header.ReadOnly, FileObject.GetExecutable())
358 DistPkg.FileList.append((ToFile, Md5Sum))
359
360 ## Tool entrance method
361 #
362 # This method mainly dispatch specific methods per the command line options.
363 # If no error found, return zero value so the caller of this tool can know
364 # if it's executed successfully or not.
365 #
366 # @param Options: command Options
367 #
368 def Main(Options = None):
369 ContentZipFile, DistFile = None, None
370
371 try:
372 DataBase = GlobalData.gDB
373 CheckEnvVariable()
374 WorkspaceDir = GlobalData.gWORKSPACE
375 if not Options.PackageFile:
376 Logger.Error("InstallPkg", OPTION_MISSING, ExtraData=ST.ERR_SPECIFY_PACKAGE)
377
378 #
379 # unzip dist.pkg file
380 #
381 DistPkg, Dep, ContentZipFile, DpPkgFileName = UnZipDp(WorkspaceDir, Options, DataBase)
382
383 #
384 # PackageList, ModuleList record the information for the meta-data
385 # files that need to be generated later
386 #
387 PackageList = []
388 ModuleList = []
389 DistPkg.PackageSurfaceArea = GetPackageList(DistPkg, Dep, WorkspaceDir, Options,
390 ContentZipFile, ModuleList, PackageList)
391
392 DistPkg.ModuleSurfaceArea = GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList)
393
394
395 GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile)
396
397 #
398 # copy "Distribution File" to directory $(WORKSPACE)/conf/upt
399 #
400 DistFileName = os.path.split(DpPkgFileName)[1]
401 DestDir = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR))
402 CreateDirectory(DestDir)
403 DestFile = os.path.normpath(os.path.join(DestDir, DistFileName))
404 if os.path.exists(DestFile):
405 FileName, Ext = os.path.splitext(DistFileName)
406 NewFileName = FileName + '_' + DistPkg.Header.GetGuid() + '_' + DistPkg.Header.GetVersion() + Ext
407 DestFile = os.path.normpath(os.path.join(DestDir, NewFileName))
408 if os.path.exists(DestFile):
409 #
410 # ask for user input the new file name
411 #
412 Logger.Info( ST.MSG_NEW_FILE_NAME_FOR_DIST)
413 Input = stdin.readline()
414 Input = Input.replace('\r', '').replace('\n', '')
415 DestFile = os.path.normpath(os.path.join(DestDir, Input))
416 copyfile(DpPkgFileName, DestFile)
417 NewDpPkgFileName = DestFile[DestFile.find(DestDir) + len(DestDir) + 1:]
418
419 #
420 # update database
421 #
422 Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE)
423 DataBase.AddDPObject(DistPkg, NewDpPkgFileName, DistFileName,
424 DistPkg.Header.RePackage)
425
426 ReturnCode = 0
427
428 except FatalError, XExcept:
429 ReturnCode = XExcept.args[0]
430 if Logger.GetLevel() <= Logger.DEBUG_9:
431 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
432 platform) + format_exc())
433 except KeyboardInterrupt:
434 ReturnCode = ABORT_ERROR
435 if Logger.GetLevel() <= Logger.DEBUG_9:
436 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
437 platform) + format_exc())
438 except:
439 ReturnCode = CODE_ERROR
440 Logger.Error(
441 "\nInstallPkg",
442 CODE_ERROR,
443 ST.ERR_UNKNOWN_FATAL_INSTALL_ERR % Options.PackageFile,
444 ExtraData=ST.MSG_SEARCH_FOR_HELP,
445 RaiseError=False
446 )
447 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
448 platform) + format_exc())
449
450 finally:
451 Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED)
452 if DistFile:
453 DistFile.Close()
454 if ContentZipFile:
455 ContentZipFile.Close()
456 if GlobalData.gUNPACK_DIR:
457 rmtree(GlobalData.gUNPACK_DIR)
458 GlobalData.gUNPACK_DIR = None
459 Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE)
460
461 if ReturnCode == 0:
462 Logger.Quiet(ST.MSG_FINISH)
463
464 return ReturnCode
465
466 ## InstallModuleContent method
467 #
468 # If this is standalone module, then Package should be none,
469 # ModulePath should be ''
470 # @param FromPath: FromPath
471 # @param NewPath: NewPath
472 # @param ModulePath: ModulePath
473 # @param Module: Module
474 # @param ContentZipFile: ContentZipFile
475 # @param WorkspaceDir: WorkspaceDir
476 # @param ModuleList: ModuleList
477 # @param Package: Package
478 #
479 def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,
480 WorkspaceDir, ModuleList, Package = None, ReadOnly = False):
481
482 if NewPath.startswith("\\") or NewPath.startswith("/"):
483 NewPath = NewPath[1:]
484
485 if not IsValidInstallPath(NewPath):
486 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%NewPath)
487
488 NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewPath,
489 ConvertPath(ModulePath)))
490 Module.SetFullPath(os.path.normpath(os.path.join(NewModuleFullPath,
491 ConvertPath(Module.GetName()) + '.inf')))
492 Module.FileList = []
493
494 for MiscFile in Module.GetMiscFileList():
495 if not MiscFile:
496 continue
497 for Item in MiscFile.GetFileList():
498 File = Item.GetURI()
499 if File.startswith("\\") or File.startswith("/"):
500 File = File[1:]
501
502 if not IsValidInstallPath(File):
503 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)
504
505 FromFile = os.path.join(FromPath, ModulePath, File)
506 Executable = Item.GetExecutable()
507 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))
508 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable)
509 if Package and ((ToFile, Md5Sum) not in Package.FileList):
510 Package.FileList.append((ToFile, Md5Sum))
511 elif Package:
512 continue
513 elif (ToFile, Md5Sum) not in Module.FileList:
514 Module.FileList.append((ToFile, Md5Sum))
515 for Item in Module.GetSourceFileList():
516 File = Item.GetSourceFile()
517 if File.startswith("\\") or File.startswith("/"):
518 File = File[1:]
519
520 if not IsValidInstallPath(File):
521 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)
522
523 FromFile = os.path.join(FromPath, ModulePath, File)
524 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))
525 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
526 if Package and ((ToFile, Md5Sum) not in Package.FileList):
527 Package.FileList.append((ToFile, Md5Sum))
528 elif Package:
529 continue
530 elif (ToFile, Md5Sum) not in Module.FileList:
531 Module.FileList.append((ToFile, Md5Sum))
532 for Item in Module.GetBinaryFileList():
533 FileNameList = Item.GetFileNameList()
534 for FileName in FileNameList:
535 File = FileName.GetFilename()
536 if File.startswith("\\") or File.startswith("/"):
537 File = File[1:]
538
539 if not IsValidInstallPath(File):
540 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)
541
542 FromFile = os.path.join(FromPath, ModulePath, File)
543 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))
544 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
545 if Package and ((ToFile, Md5Sum) not in Package.FileList):
546 Package.FileList.append((ToFile, Md5Sum))
547 elif Package:
548 continue
549 elif (ToFile, Md5Sum) not in Module.FileList:
550 Module.FileList.append((ToFile, Md5Sum))
551
552 InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly,
553 ModuleList)
554
555 ## InstallModuleContentZipFile
556 #
557 # InstallModuleContentZipFile
558 #
559 def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly,
560 ModuleList):
561 #
562 # Extract other files under current module path in content Zip file but not listed in the description
563 #
564 if ContentZipFile:
565 for FileName in ContentZipFile.GetZipFile().namelist():
566 FileName = os.path.normpath(FileName)
567 CheckPath = os.path.normpath(os.path.join(FromPath, ModulePath))
568 if FileUnderPath(FileName, CheckPath):
569 if FileName.startswith("\\") or FileName.startswith("/"):
570 FileName = FileName[1:]
571
572 if not IsValidInstallPath(FileName):
573 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
574
575 FromFile = FileName
576 ToFile = os.path.normpath(os.path.join(WorkspaceDir,
577 ConvertPath(FileName.replace(FromPath, NewPath, 1))))
578 CheckList = Module.FileList
579 if Package:
580 CheckList += Package.FileList
581 for Item in CheckList:
582 if Item[0] == ToFile:
583 break
584 else:
585 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
586 if Package and ((ToFile, Md5Sum) not in Package.FileList):
587 Package.FileList.append((ToFile, Md5Sum))
588 elif Package:
589 continue
590 elif (ToFile, Md5Sum) not in Module.FileList:
591 Module.FileList.append((ToFile, Md5Sum))
592
593 ModuleList.append((Module, Package))
594
595 ## FileUnderPath
596 # Check whether FileName started with directory specified by CheckPath
597 #
598 # @param FileName: the FileName need to be checked
599 # @param CheckPath: the path need to be checked against
600 # @return: True or False
601 #
602 def FileUnderPath(FileName, CheckPath):
603 FileName = FileName.replace('\\', '/')
604 FileName = os.path.normpath(FileName)
605 CheckPath = CheckPath.replace('\\', '/')
606 CheckPath = os.path.normpath(CheckPath)
607 if FileName.startswith(CheckPath):
608 RemainingPath = os.path.normpath(FileName.replace(CheckPath, '', 1))
609 while RemainingPath.startswith('\\') or RemainingPath.startswith('/'):
610 RemainingPath = RemainingPath[1:]
611 if FileName == os.path.normpath(os.path.join(CheckPath, RemainingPath)):
612 return True
613
614 return False
615
616 ## InstallFile
617 # Extract File from Zipfile, set file attribute, and return the Md5Sum
618 #
619 # @return: True or False
620 #
621 def InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable=False):
622 if not ContentZipFile or not ContentZipFile.UnpackFile(FromFile, ToFile):
623 Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_INSTALL_FILE_FROM_EMPTY_CONTENT%FromFile)
624
625 if ReadOnly:
626 if not Executable:
627 chmod(ToFile, stat.S_IREAD)
628 else:
629 chmod(ToFile, stat.S_IREAD|stat.S_IEXEC)
630 elif Executable:
631 chmod(ToFile, stat.S_IREAD|stat.S_IWRITE|stat.S_IEXEC)
632 else:
633 chmod(ToFile, stat.S_IREAD|stat.S_IWRITE)
634
635 Md5Sigature = md5.new(open(str(ToFile), 'rb').read())
636 Md5Sum = Md5Sigature.hexdigest()
637 return Md5Sum
638
639 ## InstallPackageContent method
640 #
641 # @param FromPath: FromPath
642 # @param ToPath: ToPath
643 # @param Package: Package
644 # @param ContentZipFile: ContentZipFile
645 # @param Dep: Dep
646 # @param WorkspaceDir: WorkspaceDir
647 # @param ModuleList: ModuleList
648 #
649 def InstallPackageContent(FromPath, ToPath, Package, ContentZipFile, Dep,
650 WorkspaceDir, ModuleList, ReadOnly = False):
651 if Dep:
652 pass
653 Package.FileList = []
654
655 if ToPath.startswith("\\") or ToPath.startswith("/"):
656 ToPath = ToPath[1:]
657
658 if not IsValidInstallPath(ToPath):
659 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%ToPath)
660
661 if FromPath.startswith("\\") or FromPath.startswith("/"):
662 FromPath = FromPath[1:]
663
664 if not IsValidInstallPath(FromPath):
665 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FromPath)
666
667 PackageFullPath = os.path.normpath(os.path.join(WorkspaceDir, ToPath))
668 for MiscFile in Package.GetMiscFileList():
669 for Item in MiscFile.GetFileList():
670 FileName = Item.GetURI()
671 if FileName.startswith("\\") or FileName.startswith("/"):
672 FileName = FileName[1:]
673
674 if not IsValidInstallPath(FileName):
675 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
676
677 FromFile = os.path.join(FromPath, FileName)
678 Executable = Item.GetExecutable()
679 ToFile = (os.path.join(PackageFullPath, ConvertPath(FileName)))
680 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable)
681 if (ToFile, Md5Sum) not in Package.FileList:
682 Package.FileList.append((ToFile, Md5Sum))
683 PackageIncludeArchList = []
684 for Item in Package.GetPackageIncludeFileList():
685 FileName = Item.GetFilePath()
686 if FileName.startswith("\\") or FileName.startswith("/"):
687 FileName = FileName[1:]
688
689 if not IsValidInstallPath(FileName):
690 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
691
692 FromFile = os.path.join(FromPath, FileName)
693 ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName)))
694 RetFile = ContentZipFile.UnpackFile(FromFile, ToFile)
695 if RetFile == '':
696 #
697 # a non-exist path in Zipfile will return '', which means an include directory in our case
698 # save the information for later DEC creation usage and also create the directory
699 #
700 PackageIncludeArchList.append([Item.GetFilePath(), Item.GetSupArchList()])
701 CreateDirectory(ToFile)
702 continue
703 if ReadOnly:
704 chmod(ToFile, stat.S_IREAD)
705 else:
706 chmod(ToFile, stat.S_IREAD|stat.S_IWRITE)
707 Md5Sigature = md5.new(open(str(ToFile), 'rb').read())
708 Md5Sum = Md5Sigature.hexdigest()
709 if (ToFile, Md5Sum) not in Package.FileList:
710 Package.FileList.append((ToFile, Md5Sum))
711 Package.SetIncludeArchList(PackageIncludeArchList)
712
713 for Item in Package.GetStandardIncludeFileList():
714 FileName = Item.GetFilePath()
715 if FileName.startswith("\\") or FileName.startswith("/"):
716 FileName = FileName[1:]
717
718 if not IsValidInstallPath(FileName):
719 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
720
721 FromFile = os.path.join(FromPath, FileName)
722 ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName)))
723 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
724 if (ToFile, Md5Sum) not in Package.FileList:
725 Package.FileList.append((ToFile, Md5Sum))
726
727 #
728 # Update package
729 #
730 Package.SetPackagePath(Package.GetPackagePath().replace(FromPath,
731 ToPath, 1))
732 Package.SetFullPath(os.path.normpath(os.path.join(PackageFullPath,
733 ConvertPath(Package.GetName()) + '.dec')))
734
735 #
736 # Install files in module
737 #
738 Module = None
739 ModuleDict = Package.GetModuleDict()
740 for ModuleGuid, ModuleVersion, ModuleName, ModulePath in ModuleDict:
741 Module = ModuleDict[ModuleGuid, ModuleVersion, ModuleName, ModulePath]
742 InstallModuleContent(FromPath, ToPath, ModulePath, Module,
743 ContentZipFile, WorkspaceDir, ModuleList, Package, ReadOnly)
744
745 ## GetDPFile method
746 #
747 # @param ZipFile: A ZipFile
748 #
749 def GetDPFile(ZipFile):
750 ContentFile = ''
751 DescFile = ''
752 for FileName in ZipFile.namelist():
753 if FileName.endswith('.content'):
754 if not ContentFile:
755 ContentFile = FileName
756 continue
757 elif FileName.endswith('.pkg'):
758 if not DescFile:
759 DescFile = FileName
760 continue
761 else:
762 continue
763
764 Logger.Error("PackagingTool", FILE_TYPE_MISMATCH,
765 ExtraData=ST.ERR_DIST_FILE_TOOMANY)
766 if not DescFile or not ContentFile:
767 Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR,
768 ExtraData=ST.ERR_DIST_FILE_TOOFEW)
769 return DescFile, ContentFile
770