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