]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/InstallPkg.py
6cb9f2533df5cd6711e573418b7f29f642988b40
[mirror_edk2.git] / BaseTools / Source / Python / UPT / InstallPkg.py
1 ## @file
2 # Install distribution package.
3 #
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 #
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8 """
9 Install a distribution package
10 """
11 ##
12 # Import Modules
13 #
14 from Core.FileHook import __FileHookOpen__
15 import os.path
16 from os import chmod
17 from os import SEEK_SET
18 from os import SEEK_END
19 import stat
20 from hashlib import md5
21 import copy
22 from sys import stdin
23 from sys import platform
24 from shutil import rmtree
25 from shutil import copyfile
26 from traceback import format_exc
27 from platform import python_version
28
29 from Logger import StringTable as ST
30 from Logger.ToolError import UNKNOWN_ERROR
31 from Logger.ToolError import FILE_UNKNOWN_ERROR
32 from Logger.ToolError import OPTION_MISSING
33 from Logger.ToolError import UPT_ALREADY_INSTALLED_ERROR
34 from Logger.ToolError import FatalError
35 from Logger.ToolError import ABORT_ERROR
36 from Logger.ToolError import CODE_ERROR
37 from Logger.ToolError import FORMAT_INVALID
38 from Logger.ToolError import FILE_TYPE_MISMATCH
39 import Logger.Log as Logger
40
41 from Library.Misc import Sdict
42 from Library.Misc import ConvertPath
43 from Library.ParserValidate import IsValidInstallPath
44 from Xml.XmlParser import DistributionPackageXml
45 from GenMetaFile.GenDecFile import PackageToDec
46 from GenMetaFile.GenInfFile import ModuleToInf
47 from Core.PackageFile import PackageFile
48 from Core.PackageFile import FILE_NOT_FOUND
49 from Core.PackageFile import FILE_CHECKSUM_FAILURE
50 from Core.PackageFile import CreateDirectory
51 from Core.DependencyRules import DependencyRules
52 from Library import GlobalData
53
54 ## InstallNewPackage
55 #
56 # @param WorkspaceDir: Workspace Directory
57 # @param Path: Package Path
58 # @param CustomPath: whether need to customize path at first
59 #
60 def InstallNewPackage(WorkspaceDir, Path, CustomPath = False):
61 if os.path.isabs(Path):
62 Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%Path)
63 elif CustomPath:
64 Logger.Info(ST.MSG_NEW_PKG_PATH)
65 else:
66 Path = ConvertPath(Path)
67 Path = os.path.normpath(Path)
68 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path))
69 if os.path.exists(FullPath):
70 Logger.Info(ST.ERR_DIR_ALREADY_EXIST%FullPath)
71 else:
72 return Path
73
74 Input = stdin.readline()
75 Input = Input.replace('\r', '').replace('\n', '')
76 if Input == '':
77 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
78 Input = Input.replace('\r', '').replace('\n', '')
79 return InstallNewPackage(WorkspaceDir, Input, False)
80
81 ## InstallNewModule
82 #
83 # @param WorkspaceDir: Workspace Directory
84 # @param Path: Standalone Module Path
85 # @param PathList: The already installed standalone module Path list
86 #
87 def InstallNewModule(WorkspaceDir, Path, PathList = None):
88 if PathList is None:
89 PathList = []
90 Path = ConvertPath(Path)
91 Path = os.path.normpath(Path)
92 FullPath = os.path.normpath(os.path.join(WorkspaceDir, Path))
93 if os.path.exists(FullPath) and FullPath not in PathList:
94 Logger.Info(ST.ERR_DIR_ALREADY_EXIST%Path)
95 elif Path == FullPath:
96 Logger.Info(ST.MSG_RELATIVE_PATH_ONLY%FullPath)
97 else:
98 return Path
99
100 Input = stdin.readline()
101 Input = Input.replace('\r', '').replace('\n', '')
102 if Input == '':
103 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
104 Input = Input.replace('\r', '').replace('\n', '')
105 return InstallNewModule(WorkspaceDir, Input, PathList)
106
107
108 ## InstallNewFile
109 #
110 # @param WorkspaceDir: Workspace Direction
111 # @param File: File
112 #
113 def InstallNewFile(WorkspaceDir, File):
114 FullPath = os.path.normpath(os.path.join(WorkspaceDir, File))
115 if os.path.exists(FullPath):
116 Logger.Info(ST.ERR_FILE_ALREADY_EXIST %File)
117 Input = stdin.readline()
118 Input = Input.replace('\r', '').replace('\n', '')
119 if Input == '':
120 Logger.Error("InstallPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
121 Input = Input.replace('\r', '').replace('\n', '')
122 return InstallNewFile(WorkspaceDir, Input)
123 else:
124 return File
125
126 ## UnZipDp
127 #
128 # UnZipDp
129 #
130 def UnZipDp(WorkspaceDir, DpPkgFileName, Index=1):
131 ContentZipFile = None
132 Logger.Quiet(ST.MSG_UZIP_PARSE_XML)
133 DistFile = PackageFile(DpPkgFileName)
134
135 DpDescFileName, ContentFileName = GetDPFile(DistFile.GetZipFile())
136
137 TempDir = os.path.normpath(os.path.join(WorkspaceDir, "Conf/.tmp%s" % str(Index)))
138 GlobalData.gUNPACK_DIR.append(TempDir)
139 DistPkgFile = DistFile.UnpackFile(DpDescFileName, os.path.normpath(os.path.join(TempDir, DpDescFileName)))
140 if not DistPkgFile:
141 Logger.Error("InstallPkg", FILE_NOT_FOUND, ST.ERR_FILE_BROKEN %DpDescFileName)
142
143 #
144 # Generate distpkg
145 #
146 DistPkgObj = DistributionPackageXml()
147 DistPkg = DistPkgObj.FromXml(DistPkgFile)
148 if DistPkg.Header.RePackage == '':
149 DistPkg.Header.RePackage = False
150 if DistPkg.Header.ReadOnly == '':
151 DistPkg.Header.ReadOnly = False
152
153 #
154 # unzip contents.zip file
155 #
156 ContentFile = DistFile.UnpackFile(ContentFileName, os.path.normpath(os.path.join(TempDir, ContentFileName)))
157 if not ContentFile:
158 Logger.Error("InstallPkg", FILE_NOT_FOUND,
159 ST.ERR_FILE_BROKEN % ContentFileName)
160
161 #
162 # Get file size
163 #
164 FileSize = os.path.getsize(ContentFile)
165
166 if FileSize != 0:
167 ContentZipFile = PackageFile(ContentFile)
168
169 #
170 # verify MD5 signature when existed
171 #
172 if DistPkg.Header.Signature != '':
173 Md5Signature = md5(__FileHookOpen__(ContentFile, 'rb').read())
174 if DistPkg.Header.Signature != Md5Signature.hexdigest():
175 ContentZipFile.Close()
176 Logger.Error("InstallPkg", FILE_CHECKSUM_FAILURE,
177 ExtraData=ContentFile)
178
179 return DistPkg, ContentZipFile, DpPkgFileName, DistFile
180
181 ## GetPackageList
182 #
183 # GetPackageList
184 #
185 def GetPackageList(DistPkg, Dep, WorkspaceDir, Options, ContentZipFile, ModuleList, PackageList):
186 NewDict = Sdict()
187 for Guid, Version, Path in DistPkg.PackageSurfaceArea:
188 PackagePath = Path
189 Package = DistPkg.PackageSurfaceArea[Guid, Version, Path]
190 Logger.Info(ST.MSG_INSTALL_PACKAGE % Package.GetName())
191 # if Dep.CheckPackageExists(Guid, Version):
192 # Logger.Info(ST.WRN_PACKAGE_EXISTED %(Guid, Version))
193 if Options.UseGuidedPkgPath:
194 GuidedPkgPath = "%s_%s_%s" % (Package.GetName(), Guid, Version)
195 NewPackagePath = InstallNewPackage(WorkspaceDir, GuidedPkgPath, Options.CustomPath)
196 else:
197 NewPackagePath = InstallNewPackage(WorkspaceDir, PackagePath, Options.CustomPath)
198 InstallPackageContent(PackagePath, NewPackagePath, Package, ContentZipFile, Dep, WorkspaceDir, ModuleList,
199 DistPkg.Header.ReadOnly)
200 PackageList.append(Package)
201
202 NewDict[Guid, Version, Package.GetPackagePath()] = Package
203
204 #
205 # Now generate meta-data files, first generate all dec for package
206 # dec should be generated before inf, and inf should be generated after
207 # all packages installed, else hard to resolve modules' package
208 # dependency (Hard to get the location of the newly installed package)
209 #
210 for Package in PackageList:
211 FilePath = PackageToDec(Package, DistPkg.Header)
212 Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read())
213 Md5Sum = Md5Signature.hexdigest()
214 if (FilePath, Md5Sum) not in Package.FileList:
215 Package.FileList.append((FilePath, Md5Sum))
216
217 return NewDict
218
219 ## GetModuleList
220 #
221 # GetModuleList
222 #
223 def GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList):
224 #
225 # ModulePathList will keep track of the standalone module path that
226 # we just installed. If a new module's path in that list
227 # (only multiple INF in one directory will be so), we will
228 # install them directly. If not, we will try to create a new directory
229 # for it.
230 #
231 ModulePathList = []
232
233 #
234 # Check module exist and install
235 #
236 Module = None
237 NewDict = Sdict()
238 for Guid, Version, Name, Path in DistPkg.ModuleSurfaceArea:
239 ModulePath = Path
240 Module = DistPkg.ModuleSurfaceArea[Guid, Version, Name, Path]
241 Logger.Info(ST.MSG_INSTALL_MODULE % Module.GetName())
242 if Dep.CheckModuleExists(Guid, Version, Name, Path):
243 Logger.Quiet(ST.WRN_MODULE_EXISTED %Path)
244 #
245 # here check for the multiple inf share the same module path cases:
246 # they should be installed into the same directory
247 #
248 ModuleFullPath = \
249 os.path.normpath(os.path.join(WorkspaceDir, ModulePath))
250 if ModuleFullPath not in ModulePathList:
251 NewModulePath = InstallNewModule(WorkspaceDir, ModulePath, ModulePathList)
252 NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewModulePath))
253 ModulePathList.append(NewModuleFullPath)
254 else:
255 NewModulePath = ModulePath
256
257 InstallModuleContent(ModulePath, NewModulePath, '', Module, ContentZipFile, WorkspaceDir, ModuleList, None,
258 DistPkg.Header.ReadOnly)
259 #
260 # Update module
261 #
262 Module.SetModulePath(Module.GetModulePath().replace(Path, NewModulePath, 1))
263
264 NewDict[Guid, Version, Name, Module.GetModulePath()] = Module
265
266 #
267 # generate all inf for modules
268 #
269 for (Module, Package) in ModuleList:
270 CheckCNameInModuleRedefined(Module, DistPkg)
271 FilePath = ModuleToInf(Module, Package, DistPkg.Header)
272 Md5Signature = md5(__FileHookOpen__(str(FilePath), 'rb').read())
273 Md5Sum = Md5Signature.hexdigest()
274 if Package:
275 if (FilePath, Md5Sum) not in Package.FileList:
276 Package.FileList.append((FilePath, Md5Sum))
277 else:
278 if (FilePath, Md5Sum) not in Module.FileList:
279 Module.FileList.append((FilePath, Md5Sum))
280 #
281 # append the module unicode files to Package FileList
282 #
283 for (FilePath, Md5Sum) in Module.FileList:
284 if str(FilePath).endswith('.uni') and Package and (FilePath, Md5Sum) not in Package.FileList:
285 Package.FileList.append((FilePath, Md5Sum))
286
287 return NewDict
288
289 ##
290 # Get all protocol/ppi/guid CNames and pcd name from all dependent DEC file
291 #
292 def GetDepProtocolPpiGuidPcdNames(DePackageObjList):
293 #
294 # [[Dec1Protocol1, Dec1Protocol2...], [Dec2Protocols...],...]
295 #
296 DependentProtocolCNames = []
297 DependentPpiCNames = []
298 DependentGuidCNames = []
299 DependentPcdNames = []
300
301 for PackageObj in DePackageObjList:
302 #
303 # Get protocol CName list from all dependent DEC file
304 #
305 ProtocolCNames = []
306 for Protocol in PackageObj.GetProtocolList():
307 if Protocol.GetCName() not in ProtocolCNames:
308 ProtocolCNames.append(Protocol.GetCName())
309
310 DependentProtocolCNames.append(ProtocolCNames)
311
312 #
313 # Get Ppi CName list from all dependent DEC file
314 #
315 PpiCNames = []
316 for Ppi in PackageObj.GetPpiList():
317 if Ppi.GetCName() not in PpiCNames:
318 PpiCNames.append(Ppi.GetCName())
319
320 DependentPpiCNames.append(PpiCNames)
321
322 #
323 # Get Guid CName list from all dependent DEC file
324 #
325 GuidCNames = []
326 for Guid in PackageObj.GetGuidList():
327 if Guid.GetCName() not in GuidCNames:
328 GuidCNames.append(Guid.GetCName())
329
330 DependentGuidCNames.append(GuidCNames)
331
332 #
333 # Get PcdName list from all dependent DEC file
334 #
335 PcdNames = []
336 for Pcd in PackageObj.GetPcdList():
337 PcdName = '.'.join([Pcd.GetTokenSpaceGuidCName(), Pcd.GetCName()])
338 if PcdName not in PcdNames:
339 PcdNames.append(PcdName)
340
341 DependentPcdNames.append(PcdNames)
342
343
344 return DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames
345
346 ##
347 # Check if protocol CName is redefined
348 #
349 def CheckProtoclCNameRedefined(Module, DependentProtocolCNames):
350 for ProtocolInModule in Module.GetProtocolList():
351 IsCNameDefined = False
352 for PackageProtocolCNames in DependentProtocolCNames:
353 if ProtocolInModule.GetCName() in PackageProtocolCNames:
354 if IsCNameDefined:
355 Logger.Error("\nUPT", FORMAT_INVALID,
356 File = Module.GetFullPath(),
357 ExtraData = \
358 ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % ProtocolInModule.GetCName())
359 else:
360 IsCNameDefined = True
361
362 ##
363 # Check if Ppi CName is redefined
364 #
365 def CheckPpiCNameRedefined(Module, DependentPpiCNames):
366 for PpiInModule in Module.GetPpiList():
367 IsCNameDefined = False
368 for PackagePpiCNames in DependentPpiCNames:
369 if PpiInModule.GetCName() in PackagePpiCNames:
370 if IsCNameDefined:
371 Logger.Error("\nUPT", FORMAT_INVALID,
372 File = Module.GetFullPath(),
373 ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PpiInModule.GetCName())
374 else:
375 IsCNameDefined = True
376
377 ##
378 # Check if Guid CName is redefined
379 #
380 def CheckGuidCNameRedefined(Module, DependentGuidCNames):
381 for GuidInModule in Module.GetGuidList():
382 IsCNameDefined = False
383 for PackageGuidCNames in DependentGuidCNames:
384 if GuidInModule.GetCName() in PackageGuidCNames:
385 if IsCNameDefined:
386 Logger.Error("\nUPT", FORMAT_INVALID,
387 File = Module.GetFullPath(),
388 ExtraData = \
389 ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % GuidInModule.GetCName())
390 else:
391 IsCNameDefined = True
392
393 ##
394 # Check if PcdName is redefined
395 #
396 def CheckPcdNameRedefined(Module, DependentPcdNames):
397 PcdObjs = []
398 if not Module.GetBinaryFileList():
399 PcdObjs += Module.GetPcdList()
400 else:
401 Binary = Module.GetBinaryFileList()[0]
402 for AsBuild in Binary.GetAsBuiltList():
403 PcdObjs += AsBuild.GetPatchPcdList() + AsBuild.GetPcdExList()
404
405 for PcdObj in PcdObjs:
406 PcdName = '.'.join([PcdObj.GetTokenSpaceGuidCName(), PcdObj.GetCName()])
407 IsPcdNameDefined = False
408 for PcdNames in DependentPcdNames:
409 if PcdName in PcdNames:
410 if IsPcdNameDefined:
411 Logger.Error("\nUPT", FORMAT_INVALID,
412 File = Module.GetFullPath(),
413 ExtraData = ST.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC % PcdName)
414 else:
415 IsPcdNameDefined = True
416
417 ##
418 # Check if any Protocol/Ppi/Guid and Pcd name is redefined in its dependent DEC files
419 #
420 def CheckCNameInModuleRedefined(Module, DistPkg):
421 DePackageObjList = []
422 #
423 # Get all dependent package objects
424 #
425 for Obj in Module.GetPackageDependencyList():
426 Guid = Obj.GetGuid()
427 Version = Obj.GetVersion()
428 for Key in DistPkg.PackageSurfaceArea:
429 if Key[0] == Guid and Key[1] == Version:
430 if DistPkg.PackageSurfaceArea[Key] not in DePackageObjList:
431 DePackageObjList.append(DistPkg.PackageSurfaceArea[Key])
432
433 DependentProtocolCNames, DependentPpiCNames, DependentGuidCNames, DependentPcdNames = \
434 GetDepProtocolPpiGuidPcdNames(DePackageObjList)
435
436 CheckProtoclCNameRedefined(Module, DependentProtocolCNames)
437 CheckPpiCNameRedefined(Module, DependentPpiCNames)
438 CheckGuidCNameRedefined(Module, DependentGuidCNames)
439 CheckPcdNameRedefined(Module, DependentPcdNames)
440
441 ## GenToolMisc
442 #
443 # GenToolMisc
444 #
445 #
446 def GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile):
447 ToolObject = DistPkg.Tools
448 MiscObject = DistPkg.MiscellaneousFiles
449 DistPkg.FileList = []
450 FileList = []
451 ToolFileNum = 0
452 FileNum = 0
453 RootDir = WorkspaceDir
454
455 #
456 # FileList stores both tools files and misc files
457 # Misc file list must be appended to FileList *AFTER* Tools file list
458 #
459 if ToolObject:
460 FileList += ToolObject.GetFileList()
461 ToolFileNum = len(ToolObject.GetFileList())
462 if 'EDK_TOOLS_PATH' in os.environ:
463 RootDir = os.environ['EDK_TOOLS_PATH']
464 if MiscObject:
465 FileList += MiscObject.GetFileList()
466 for FileObject in FileList:
467 FileNum += 1
468 if FileNum > ToolFileNum:
469 #
470 # Misc files, root should be changed to WORKSPACE
471 #
472 RootDir = WorkspaceDir
473 File = ConvertPath(FileObject.GetURI())
474 ToFile = os.path.normpath(os.path.join(RootDir, File))
475 if os.path.exists(ToFile):
476 Logger.Info( ST.WRN_FILE_EXISTED % ToFile )
477 #
478 # ask for user input the new file name
479 #
480 Logger.Info( ST.MSG_NEW_FILE_NAME)
481 Input = stdin.readline()
482 Input = Input.replace('\r', '').replace('\n', '')
483 OrigPath = os.path.split(ToFile)[0]
484 ToFile = os.path.normpath(os.path.join(OrigPath, Input))
485 FromFile = os.path.join(FileObject.GetURI())
486 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, DistPkg.Header.ReadOnly, FileObject.GetExecutable())
487 DistPkg.FileList.append((ToFile, Md5Sum))
488
489 ## Tool entrance method
490 #
491 # This method mainly dispatch specific methods per the command line options.
492 # If no error found, return zero value so the caller of this tool can know
493 # if it's executed successfully or not.
494 #
495 # @param Options: command Options
496 #
497 def Main(Options = None):
498 try:
499 DataBase = GlobalData.gDB
500 WorkspaceDir = GlobalData.gWORKSPACE
501 if not Options.PackageFile:
502 Logger.Error("InstallPkg", OPTION_MISSING, ExtraData=ST.ERR_SPECIFY_PACKAGE)
503
504 # Get all Dist Info
505 DistInfoList = []
506 DistPkgList = []
507 Index = 1
508 for ToBeInstalledDist in Options.PackageFile:
509 #
510 # unzip dist.pkg file
511 #
512 DistInfoList.append(UnZipDp(WorkspaceDir, ToBeInstalledDist, Index))
513 DistPkgList.append(DistInfoList[-1][0])
514 Index += 1
515
516 #
517 # Add dist
518 #
519 GlobalData.gTO_BE_INSTALLED_DIST_LIST.append(DistInfoList[-1][0])
520
521 # Check for dependency
522 Dep = DependencyRules(DataBase, DistPkgList)
523
524 for ToBeInstalledDist in DistInfoList:
525 CheckInstallDpx(Dep, ToBeInstalledDist[0], ToBeInstalledDist[2])
526
527 #
528 # Install distribution
529 #
530 InstallDp(ToBeInstalledDist[0], ToBeInstalledDist[2], ToBeInstalledDist[1],
531 Options, Dep, WorkspaceDir, DataBase)
532 ReturnCode = 0
533
534 except FatalError as XExcept:
535 ReturnCode = XExcept.args[0]
536 if Logger.GetLevel() <= Logger.DEBUG_9:
537 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())
538
539 except KeyboardInterrupt:
540 ReturnCode = ABORT_ERROR
541 if Logger.GetLevel() <= Logger.DEBUG_9:
542 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + format_exc())
543
544 except:
545 ReturnCode = CODE_ERROR
546 Logger.Error(
547 "\nInstallPkg",
548 CODE_ERROR,
549 ST.ERR_UNKNOWN_FATAL_INSTALL_ERR % Options.PackageFile,
550 ExtraData=ST.MSG_SEARCH_FOR_HELP,
551 RaiseError=False
552 )
553 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(),
554 platform) + format_exc())
555 finally:
556 Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_STARTED)
557 for ToBeInstalledDist in DistInfoList:
558 if ToBeInstalledDist[3]:
559 ToBeInstalledDist[3].Close()
560 if ToBeInstalledDist[1]:
561 ToBeInstalledDist[1].Close()
562 for TempDir in GlobalData.gUNPACK_DIR:
563 rmtree(TempDir)
564 GlobalData.gUNPACK_DIR = []
565 Logger.Quiet(ST.MSG_REMOVE_TEMP_FILE_DONE)
566 if ReturnCode == 0:
567 Logger.Quiet(ST.MSG_FINISH)
568 return ReturnCode
569
570 # BackupDist method
571 #
572 # This method will backup the Distribution file into the $(WORKSPACE)/conf/upt, and rename it
573 # if there is already a same-named distribution existed.
574 #
575 # @param DpPkgFileName: The distribution path
576 # @param Guid: The distribution Guid
577 # @param Version: The distribution Version
578 # @param WorkspaceDir: The workspace directory
579 # @retval NewDpPkgFileName: The exact backup file name
580 #
581 def BackupDist(DpPkgFileName, Guid, Version, WorkspaceDir):
582 DistFileName = os.path.split(DpPkgFileName)[1]
583 DestDir = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR))
584 CreateDirectory(DestDir)
585 DestFile = os.path.normpath(os.path.join(DestDir, DistFileName))
586 if os.path.exists(DestFile):
587 FileName, Ext = os.path.splitext(DistFileName)
588 NewFileName = FileName + '_' + Guid + '_' + Version + Ext
589 DestFile = os.path.normpath(os.path.join(DestDir, NewFileName))
590 if os.path.exists(DestFile):
591 #
592 # ask for user input the new file name
593 #
594 Logger.Info( ST.MSG_NEW_FILE_NAME_FOR_DIST)
595 Input = stdin.readline()
596 Input = Input.replace('\r', '').replace('\n', '')
597 DestFile = os.path.normpath(os.path.join(DestDir, Input))
598 copyfile(DpPkgFileName, DestFile)
599 NewDpPkgFileName = DestFile[DestFile.find(DestDir) + len(DestDir) + 1:]
600 return NewDpPkgFileName
601
602 ## CheckInstallDpx method
603 #
604 # check whether distribution could be installed
605 #
606 # @param Dep: the DependencyRules instance that used to check dependency
607 # @param DistPkg: the distribution object
608 #
609 def CheckInstallDpx(Dep, DistPkg, DistPkgFileName):
610 #
611 # Check distribution package installed or not
612 #
613 if Dep.CheckDpExists(DistPkg.Header.GetGuid(),
614 DistPkg.Header.GetVersion()):
615 Logger.Error("InstallPkg",
616 UPT_ALREADY_INSTALLED_ERROR,
617 ST.WRN_DIST_PKG_INSTALLED % os.path.basename(DistPkgFileName))
618 #
619 # Check distribution dependency (all module dependency should be
620 # satisfied)
621 #
622 if not Dep.CheckInstallDpDepexSatisfied(DistPkg):
623 Logger.Error("InstallPkg", UNKNOWN_ERROR,
624 ST.ERR_PACKAGE_NOT_MATCH_DEPENDENCY,
625 ExtraData=DistPkg.Header.Name)
626
627 ## InstallModuleContent method
628 #
629 # If this is standalone module, then Package should be none,
630 # ModulePath should be ''
631 # @param FromPath: FromPath
632 # @param NewPath: NewPath
633 # @param ModulePath: ModulePath
634 # @param Module: Module
635 # @param ContentZipFile: ContentZipFile
636 # @param WorkspaceDir: WorkspaceDir
637 # @param ModuleList: ModuleList
638 # @param Package: Package
639 #
640 def InstallModuleContent(FromPath, NewPath, ModulePath, Module, ContentZipFile,
641 WorkspaceDir, ModuleList, Package = None, ReadOnly = False):
642
643 if NewPath.startswith("\\") or NewPath.startswith("/"):
644 NewPath = NewPath[1:]
645
646 if not IsValidInstallPath(NewPath):
647 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%NewPath)
648
649 NewModuleFullPath = os.path.normpath(os.path.join(WorkspaceDir, NewPath,
650 ConvertPath(ModulePath)))
651 Module.SetFullPath(os.path.normpath(os.path.join(NewModuleFullPath,
652 ConvertPath(Module.GetName()) + '.inf')))
653 Module.FileList = []
654
655 for MiscFile in Module.GetMiscFileList():
656 if not MiscFile:
657 continue
658 for Item in MiscFile.GetFileList():
659 File = Item.GetURI()
660 if File.startswith("\\") or File.startswith("/"):
661 File = File[1:]
662
663 if not IsValidInstallPath(File):
664 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)
665
666 FromFile = os.path.join(FromPath, ModulePath, File)
667 Executable = Item.GetExecutable()
668 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))
669 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable)
670 if Package and ((ToFile, Md5Sum) not in Package.FileList):
671 Package.FileList.append((ToFile, Md5Sum))
672 elif Package:
673 continue
674 elif (ToFile, Md5Sum) not in Module.FileList:
675 Module.FileList.append((ToFile, Md5Sum))
676 for Item in Module.GetSourceFileList():
677 File = Item.GetSourceFile()
678 if File.startswith("\\") or File.startswith("/"):
679 File = File[1:]
680
681 if not IsValidInstallPath(File):
682 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)
683
684 FromFile = os.path.join(FromPath, ModulePath, File)
685 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))
686 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
687 if Package and ((ToFile, Md5Sum) not in Package.FileList):
688 Package.FileList.append((ToFile, Md5Sum))
689 elif Package:
690 continue
691 elif (ToFile, Md5Sum) not in Module.FileList:
692 Module.FileList.append((ToFile, Md5Sum))
693 for Item in Module.GetBinaryFileList():
694 FileNameList = Item.GetFileNameList()
695 for FileName in FileNameList:
696 File = FileName.GetFilename()
697 if File.startswith("\\") or File.startswith("/"):
698 File = File[1:]
699
700 if not IsValidInstallPath(File):
701 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%File)
702
703 FromFile = os.path.join(FromPath, ModulePath, File)
704 ToFile = os.path.normpath(os.path.join(NewModuleFullPath, ConvertPath(File)))
705 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
706 if Package and ((ToFile, Md5Sum) not in Package.FileList):
707 Package.FileList.append((ToFile, Md5Sum))
708 elif Package:
709 continue
710 elif (ToFile, Md5Sum) not in Module.FileList:
711 Module.FileList.append((ToFile, Md5Sum))
712
713 InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly,
714 ModuleList)
715
716 ## InstallModuleContentZipFile
717 #
718 # InstallModuleContentZipFile
719 #
720 def InstallModuleContentZipFile(ContentZipFile, FromPath, ModulePath, WorkspaceDir, NewPath, Module, Package, ReadOnly,
721 ModuleList):
722 #
723 # Extract other files under current module path in content Zip file but not listed in the description
724 #
725 if ContentZipFile:
726 for FileName in ContentZipFile.GetZipFile().namelist():
727 FileName = os.path.normpath(FileName)
728 CheckPath = os.path.normpath(os.path.join(FromPath, ModulePath))
729 if FileUnderPath(FileName, CheckPath):
730 if FileName.startswith("\\") or FileName.startswith("/"):
731 FileName = FileName[1:]
732
733 if not IsValidInstallPath(FileName):
734 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
735
736 FromFile = FileName
737 ToFile = os.path.normpath(os.path.join(WorkspaceDir,
738 ConvertPath(FileName.replace(FromPath, NewPath, 1))))
739 CheckList = copy.copy(Module.FileList)
740 if Package:
741 CheckList += Package.FileList
742 for Item in CheckList:
743 if Item[0] == ToFile:
744 break
745 else:
746 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
747 if Package and ((ToFile, Md5Sum) not in Package.FileList):
748 Package.FileList.append((ToFile, Md5Sum))
749 elif Package:
750 continue
751 elif (ToFile, Md5Sum) not in Module.FileList:
752 Module.FileList.append((ToFile, Md5Sum))
753
754 ModuleList.append((Module, Package))
755
756 ## FileUnderPath
757 # Check whether FileName started with directory specified by CheckPath
758 #
759 # @param FileName: the FileName need to be checked
760 # @param CheckPath: the path need to be checked against
761 # @return: True or False
762 #
763 def FileUnderPath(FileName, CheckPath):
764 FileName = FileName.replace('\\', '/')
765 FileName = os.path.normpath(FileName)
766 CheckPath = CheckPath.replace('\\', '/')
767 CheckPath = os.path.normpath(CheckPath)
768 if FileName.startswith(CheckPath):
769 RemainingPath = os.path.normpath(FileName.replace(CheckPath, '', 1))
770 while RemainingPath.startswith('\\') or RemainingPath.startswith('/'):
771 RemainingPath = RemainingPath[1:]
772 if FileName == os.path.normpath(os.path.join(CheckPath, RemainingPath)):
773 return True
774
775 return False
776
777 ## InstallFile
778 # Extract File from Zipfile, set file attribute, and return the Md5Sum
779 #
780 # @return: True or False
781 #
782 def InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable=False):
783 if os.path.exists(os.path.normpath(ToFile)):
784 pass
785 else:
786 if not ContentZipFile or not ContentZipFile.UnpackFile(FromFile, ToFile):
787 Logger.Error("UPT", FILE_NOT_FOUND, ST.ERR_INSTALL_FILE_FROM_EMPTY_CONTENT % FromFile)
788
789 if ReadOnly:
790 if not Executable:
791 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
792 else:
793 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
794 elif Executable:
795 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP |
796 stat.S_IWOTH | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
797 else:
798 chmod(ToFile, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
799
800 Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read())
801 Md5Sum = Md5Signature.hexdigest()
802
803 return Md5Sum
804
805 ## InstallPackageContent method
806 #
807 # @param FromPath: FromPath
808 # @param ToPath: ToPath
809 # @param Package: Package
810 # @param ContentZipFile: ContentZipFile
811 # @param Dep: Dep
812 # @param WorkspaceDir: WorkspaceDir
813 # @param ModuleList: ModuleList
814 #
815 def InstallPackageContent(FromPath, ToPath, Package, ContentZipFile, Dep,
816 WorkspaceDir, ModuleList, ReadOnly = False):
817 if Dep:
818 pass
819 Package.FileList = []
820
821 if ToPath.startswith("\\") or ToPath.startswith("/"):
822 ToPath = ToPath[1:]
823
824 if not IsValidInstallPath(ToPath):
825 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%ToPath)
826
827 if FromPath.startswith("\\") or FromPath.startswith("/"):
828 FromPath = FromPath[1:]
829
830 if not IsValidInstallPath(FromPath):
831 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FromPath)
832
833 PackageFullPath = os.path.normpath(os.path.join(WorkspaceDir, ToPath))
834 for MiscFile in Package.GetMiscFileList():
835 for Item in MiscFile.GetFileList():
836 FileName = Item.GetURI()
837 if FileName.startswith("\\") or FileName.startswith("/"):
838 FileName = FileName[1:]
839
840 if not IsValidInstallPath(FileName):
841 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
842
843 FromFile = os.path.join(FromPath, FileName)
844 Executable = Item.GetExecutable()
845 ToFile = (os.path.join(PackageFullPath, ConvertPath(FileName)))
846 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly, Executable)
847 if (ToFile, Md5Sum) not in Package.FileList:
848 Package.FileList.append((ToFile, Md5Sum))
849 PackageIncludeArchList = []
850 for Item in Package.GetPackageIncludeFileList():
851 FileName = Item.GetFilePath()
852 if FileName.startswith("\\") or FileName.startswith("/"):
853 FileName = FileName[1:]
854
855 if not IsValidInstallPath(FileName):
856 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
857
858 FromFile = os.path.join(FromPath, FileName)
859 ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName)))
860 RetFile = ContentZipFile.UnpackFile(FromFile, ToFile)
861 if RetFile == '':
862 #
863 # a non-exist path in Zipfile will return '', which means an include directory in our case
864 # save the information for later DEC creation usage and also create the directory
865 #
866 PackageIncludeArchList.append([Item.GetFilePath(), Item.GetSupArchList()])
867 CreateDirectory(ToFile)
868 continue
869 if ReadOnly:
870 chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
871 else:
872 chmod(ToFile, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH|stat.S_IWUSR|stat.S_IWGRP|stat.S_IWOTH)
873 Md5Signature = md5(__FileHookOpen__(str(ToFile), 'rb').read())
874 Md5Sum = Md5Signature.hexdigest()
875 if (ToFile, Md5Sum) not in Package.FileList:
876 Package.FileList.append((ToFile, Md5Sum))
877 Package.SetIncludeArchList(PackageIncludeArchList)
878
879 for Item in Package.GetStandardIncludeFileList():
880 FileName = Item.GetFilePath()
881 if FileName.startswith("\\") or FileName.startswith("/"):
882 FileName = FileName[1:]
883
884 if not IsValidInstallPath(FileName):
885 Logger.Error("UPT", FORMAT_INVALID, ST.ERR_FILE_NAME_INVALIDE%FileName)
886
887 FromFile = os.path.join(FromPath, FileName)
888 ToFile = os.path.normpath(os.path.join(PackageFullPath, ConvertPath(FileName)))
889 Md5Sum = InstallFile(ContentZipFile, FromFile, ToFile, ReadOnly)
890 if (ToFile, Md5Sum) not in Package.FileList:
891 Package.FileList.append((ToFile, Md5Sum))
892
893 #
894 # Update package
895 #
896 Package.SetPackagePath(Package.GetPackagePath().replace(FromPath,
897 ToPath, 1))
898 Package.SetFullPath(os.path.normpath(os.path.join(PackageFullPath,
899 ConvertPath(Package.GetName()) + '.dec')))
900
901 #
902 # Install files in module
903 #
904 Module = None
905 ModuleDict = Package.GetModuleDict()
906 for ModuleGuid, ModuleVersion, ModuleName, ModulePath in ModuleDict:
907 Module = ModuleDict[ModuleGuid, ModuleVersion, ModuleName, ModulePath]
908 InstallModuleContent(FromPath, ToPath, ModulePath, Module,
909 ContentZipFile, WorkspaceDir, ModuleList, Package, ReadOnly)
910
911 ## GetDPFile method
912 #
913 # @param ZipFile: A ZipFile
914 #
915 def GetDPFile(ZipFile):
916 ContentFile = ''
917 DescFile = ''
918 for FileName in ZipFile.namelist():
919 if FileName.endswith('.content'):
920 if not ContentFile:
921 ContentFile = FileName
922 continue
923 elif FileName.endswith('.pkg'):
924 if not DescFile:
925 DescFile = FileName
926 continue
927 else:
928 continue
929
930 Logger.Error("PackagingTool", FILE_TYPE_MISMATCH,
931 ExtraData=ST.ERR_DIST_FILE_TOOMANY)
932 if not DescFile or not ContentFile:
933 Logger.Error("PackagingTool", FILE_UNKNOWN_ERROR,
934 ExtraData=ST.ERR_DIST_FILE_TOOFEW)
935 return DescFile, ContentFile
936
937 ## InstallDp method
938 #
939 # Install the distribution to current workspace
940 #
941 def InstallDp(DistPkg, DpPkgFileName, ContentZipFile, Options, Dep, WorkspaceDir, DataBase):
942 #
943 # PackageList, ModuleList record the information for the meta-data
944 # files that need to be generated later
945 #
946 PackageList = []
947 ModuleList = []
948 DistPkg.PackageSurfaceArea = GetPackageList(DistPkg, Dep, WorkspaceDir, Options,
949 ContentZipFile, ModuleList, PackageList)
950
951 DistPkg.ModuleSurfaceArea = GetModuleList(DistPkg, Dep, WorkspaceDir, ContentZipFile, ModuleList)
952
953 GenToolMisc(DistPkg, WorkspaceDir, ContentZipFile)
954
955 #
956 # copy "Distribution File" to directory $(WORKSPACE)/conf/upt
957 #
958 DistFileName = os.path.split(DpPkgFileName)[1]
959 NewDpPkgFileName = BackupDist(DpPkgFileName, DistPkg.Header.GetGuid(), DistPkg.Header.GetVersion(), WorkspaceDir)
960
961 #
962 # update database
963 #
964 Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE)
965 DataBase.AddDPObject(DistPkg, NewDpPkgFileName, DistFileName,
966 DistPkg.Header.RePackage)
967