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