2 # Install distribution package.
4 # Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
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
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.
15 Install a distribution package
20 from Core
.FileHook
import __FileHookOpen__
23 from os
import SEEK_SET
24 from os
import SEEK_END
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
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
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
62 # @param WorkspaceDir: Workspace Directory
63 # @param Path: Package Path
64 # @param CustomPath: whether need to customize path at first
66 def InstallNewPackage(WorkspaceDir
, Path
, CustomPath
= False):
67 if os
.path
.isabs(Path
):
68 Logger
.Info(ST
.MSG_RELATIVE_PATH_ONLY
%Path
)
70 Logger
.Info(ST
.MSG_NEW_PKG_PATH
)
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
)
80 Input
= stdin
.readline()
81 Input
= Input
.replace('\r', '').replace('\n', '')
83 Logger
.Error("InstallPkg", UNKNOWN_ERROR
, ST
.ERR_USER_INTERRUPT
)
84 Input
= Input
.replace('\r', '').replace('\n', '')
85 return InstallNewPackage(WorkspaceDir
, Input
, False)
89 # @param WorkspaceDir: Workspace Directory
90 # @param Path: Standalone Module Path
91 # @param PathList: The already installed standalone module Path list
93 def InstallNewModule(WorkspaceDir
, Path
, PathList
= None):
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
)
106 Input
= stdin
.readline()
107 Input
= Input
.replace('\r', '').replace('\n', '')
109 Logger
.Error("InstallPkg", UNKNOWN_ERROR
, ST
.ERR_USER_INTERRUPT
)
110 Input
= Input
.replace('\r', '').replace('\n', '')
111 return InstallNewModule(WorkspaceDir
, Input
, PathList
)
116 # @param WorkspaceDir: Workspace Direction
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', '')
126 Logger
.Error("InstallPkg", UNKNOWN_ERROR
, ST
.ERR_USER_INTERRUPT
)
127 Input
= Input
.replace('\r', '').replace('\n', '')
128 return InstallNewFile(WorkspaceDir
, Input
)
136 def UnZipDp(WorkspaceDir
, DpPkgFileName
, Index
=1):
137 ContentZipFile
= None
138 Logger
.Quiet(ST
.MSG_UZIP_PARSE_XML
)
139 DistFile
= PackageFile(DpPkgFileName
)
141 DpDescFileName
, ContentFileName
= GetDPFile(DistFile
.GetZipFile())
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
)))
147 Logger
.Error("InstallPkg", FILE_NOT_FOUND
, ST
.ERR_FILE_BROKEN
%DpDescFileName
)
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
160 # unzip contents.zip file
162 ContentFile
= DistFile
.UnpackFile(ContentFileName
, os
.path
.normpath(os
.path
.join(TempDir
, ContentFileName
)))
164 Logger
.Error("InstallPkg", FILE_NOT_FOUND
,
165 ST
.ERR_FILE_BROKEN
% ContentFileName
)
170 FileSize
= os
.path
.getsize(ContentFile
)
173 ContentZipFile
= PackageFile(ContentFile
)
176 # verify MD5 signature when existed
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
)
185 return DistPkg
, ContentZipFile
, DpPkgFileName
, DistFile
191 def GetPackageList(DistPkg
, Dep
, WorkspaceDir
, Options
, ContentZipFile
, ModuleList
, PackageList
):
193 for Guid
, Version
, Path
in DistPkg
.PackageSurfaceArea
:
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
)
203 NewPackagePath
= InstallNewPackage(WorkspaceDir
, PackagePath
, Options
.CustomPath
)
204 InstallPackageContent(PackagePath
, NewPackagePath
, Package
, ContentZipFile
, Dep
, WorkspaceDir
, ModuleList
,
205 DistPkg
.Header
.ReadOnly
)
206 PackageList
.append(Package
)
208 NewDict
[Guid
, Version
, Package
.GetPackagePath()] = Package
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)
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
))
229 def GetModuleList(DistPkg
, Dep
, WorkspaceDir
, ContentZipFile
, ModuleList
):
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
240 # Check module exist and install
244 for Guid
, Version
, Name
, Path
in DistPkg
.ModuleSurfaceArea
:
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
)
251 # here check for the multiple inf share the same module path cases:
252 # they should be installed into the same directory
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
)
261 NewModulePath
= ModulePath
263 InstallModuleContent(ModulePath
, NewModulePath
, '', Module
, ContentZipFile
, WorkspaceDir
, ModuleList
, None,
264 DistPkg
.Header
.ReadOnly
)
268 Module
.SetModulePath(Module
.GetModulePath().replace(Path
, NewModulePath
, 1))
270 NewDict
[Guid
, Version
, Name
, Module
.GetModulePath()] = Module
273 # generate all inf for modules
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()
281 if (FilePath
, Md5Sum
) not in Package
.FileList
:
282 Package
.FileList
.append((FilePath
, Md5Sum
))
284 if (FilePath
, Md5Sum
) not in Module
.FileList
:
285 Module
.FileList
.append((FilePath
, Md5Sum
))
287 # append the module unicode files to Package FileList
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
))
296 # Get all protocol/ppi/guid CNames and pcd name from all dependent DEC file
298 def GetDepProtocolPpiGuidPcdNames(DePackageObjList
):
300 # [[Dec1Protocol1, Dec1Protocol2...], [Dec2Protocols...],...]
302 DependentProtocolCNames
= []
303 DependentPpiCNames
= []
304 DependentGuidCNames
= []
305 DependentPcdNames
= []
307 for PackageObj
in DePackageObjList
:
309 # Get protocol CName list from all dependent DEC file
312 for Protocol
in PackageObj
.GetProtocolList():
313 if Protocol
.GetCName() not in ProtocolCNames
:
314 ProtocolCNames
.append(Protocol
.GetCName())
316 DependentProtocolCNames
.append(ProtocolCNames
)
319 # Get Ppi CName list from all dependent DEC file
322 for Ppi
in PackageObj
.GetPpiList():
323 if Ppi
.GetCName() not in PpiCNames
:
324 PpiCNames
.append(Ppi
.GetCName())
326 DependentPpiCNames
.append(PpiCNames
)
329 # Get Guid CName list from all dependent DEC file
332 for Guid
in PackageObj
.GetGuidList():
333 if Guid
.GetCName() not in GuidCNames
:
334 GuidCNames
.append(Guid
.GetCName())
336 DependentGuidCNames
.append(GuidCNames
)
339 # Get PcdName list from all dependent DEC file
342 for Pcd
in PackageObj
.GetPcdList():
343 PcdName
= '.'.join([Pcd
.GetTokenSpaceGuidCName(), Pcd
.GetCName()])
344 if PcdName
not in PcdNames
:
345 PcdNames
.append(PcdName
)
347 DependentPcdNames
.append(PcdNames
)
350 return DependentProtocolCNames
, DependentPpiCNames
, DependentGuidCNames
, DependentPcdNames
353 # Check if protocol CName is redefined
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
:
361 Logger
.Error("\nUPT", FORMAT_INVALID
,
362 File
= Module
.GetFullPath(),
364 ST
.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC
% ProtocolInModule
.GetCName())
366 IsCNameDefined
= True
369 # Check if Ppi CName is redefined
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
:
377 Logger
.Error("\nUPT", FORMAT_INVALID
,
378 File
= Module
.GetFullPath(),
379 ExtraData
= ST
.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC
% PpiInModule
.GetCName())
381 IsCNameDefined
= True
384 # Check if Guid CName is redefined
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
:
392 Logger
.Error("\nUPT", FORMAT_INVALID
,
393 File
= Module
.GetFullPath(),
395 ST
.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC
% GuidInModule
.GetCName())
397 IsCNameDefined
= True
400 # Check if PcdName is redefined
402 def CheckPcdNameRedefined(Module
, DependentPcdNames
):
404 if not Module
.GetBinaryFileList():
405 PcdObjs
+= Module
.GetPcdList()
407 Binary
= Module
.GetBinaryFileList()[0]
408 for AsBuild
in Binary
.GetAsBuiltList():
409 PcdObjs
+= AsBuild
.GetPatchPcdList() + AsBuild
.GetPcdExList()
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
:
417 Logger
.Error("\nUPT", FORMAT_INVALID
,
418 File
= Module
.GetFullPath(),
419 ExtraData
= ST
.ERR_INF_PARSER_ITEM_DUPLICATE_IN_DEC
% PcdName
)
421 IsPcdNameDefined
= True
424 # Check if any Protocol/Ppi/Guid and Pcd name is redefined in its dependent DEC files
426 def CheckCNameInModuleRedefined(Module
, DistPkg
):
427 DePackageObjList
= []
429 # Get all dependent package objects
431 for Obj
in Module
.GetPackageDependencyList():
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
])
439 DependentProtocolCNames
, DependentPpiCNames
, DependentGuidCNames
, DependentPcdNames
= \
440 GetDepProtocolPpiGuidPcdNames(DePackageObjList
)
442 CheckProtoclCNameRedefined(Module
, DependentProtocolCNames
)
443 CheckPpiCNameRedefined(Module
, DependentPpiCNames
)
444 CheckGuidCNameRedefined(Module
, DependentGuidCNames
)
445 CheckPcdNameRedefined(Module
, DependentPcdNames
)
452 def GenToolMisc(DistPkg
, WorkspaceDir
, ContentZipFile
):
453 ToolObject
= DistPkg
.Tools
454 MiscObject
= DistPkg
.MiscellaneousFiles
455 DistPkg
.FileList
= []
459 RootDir
= WorkspaceDir
462 # FileList stores both tools files and misc files
463 # Misc file list must be appended to FileList *AFTER* Tools file list
466 FileList
+= ToolObject
.GetFileList()
467 ToolFileNum
= len(ToolObject
.GetFileList())
468 if 'EDK_TOOLS_PATH' in os
.environ
:
469 RootDir
= os
.environ
['EDK_TOOLS_PATH']
471 FileList
+= MiscObject
.GetFileList()
472 for FileObject
in FileList
:
474 if FileNum
> ToolFileNum
:
476 # Misc files, root should be changed to WORKSPACE
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
)
484 # ask for user input the new file name
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
))
495 ## Tool entrance method
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.
501 # @param Options: command Options
503 def Main(Options
= None):
505 DataBase
= GlobalData
.gDB
506 WorkspaceDir
= GlobalData
.gWORKSPACE
507 if not Options
.PackageFile
:
508 Logger
.Error("InstallPkg", OPTION_MISSING
, ExtraData
=ST
.ERR_SPECIFY_PACKAGE
)
514 for ToBeInstalledDist
in Options
.PackageFile
:
516 # unzip dist.pkg file
518 DistInfoList
.append(UnZipDp(WorkspaceDir
, ToBeInstalledDist
, Index
))
519 DistPkgList
.append(DistInfoList
[-1][0])
525 GlobalData
.gTO_BE_INSTALLED_DIST_LIST
.append(DistInfoList
[-1][0])
527 # Check for dependency
528 Dep
= DependencyRules(DataBase
, DistPkgList
)
530 for ToBeInstalledDist
in DistInfoList
:
531 CheckInstallDpx(Dep
, ToBeInstalledDist
[0], ToBeInstalledDist
[2])
534 # Install distribution
536 InstallDp(ToBeInstalledDist
[0], ToBeInstalledDist
[2], ToBeInstalledDist
[1],
537 Options
, Dep
, WorkspaceDir
, DataBase
)
540 except FatalError
, 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())
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())
551 ReturnCode
= CODE_ERROR
555 ST
.ERR_UNKNOWN_FATAL_INSTALL_ERR
% Options
.PackageFile
,
556 ExtraData
=ST
.MSG_SEARCH_FOR_HELP
,
559 Logger
.Quiet(ST
.MSG_PYTHON_ON
% (python_version(),
560 platform
) + format_exc())
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
:
570 GlobalData
.gUNPACK_DIR
= []
571 Logger
.Quiet(ST
.MSG_REMOVE_TEMP_FILE_DONE
)
573 Logger
.Quiet(ST
.MSG_FINISH
)
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.
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
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
):
598 # ask for user input the new file name
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
608 ## CheckInstallDpx method
610 # check whether distribution could be installed
612 # @param Dep: the DependencyRules instance that used to check dependency
613 # @param DistPkg: the distribution object
615 def CheckInstallDpx(Dep
, DistPkg
, DistPkgFileName
):
617 # Check distribution package installed or not
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
))
625 # Check distribution dependency (all module dependency should be
628 if not Dep
.CheckInstallDpDepexSatisfied(DistPkg
):
629 Logger
.Error("InstallPkg", UNKNOWN_ERROR
,
630 ST
.ERR_PACKAGE_NOT_MATCH_DEPENDENCY
,
631 ExtraData
=DistPkg
.Header
.Name
)
633 ## InstallModuleContent method
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
646 def InstallModuleContent(FromPath
, NewPath
, ModulePath
, Module
, ContentZipFile
,
647 WorkspaceDir
, ModuleList
, Package
= None, ReadOnly
= False):
649 if NewPath
.startswith("\\") or NewPath
.startswith("/"):
650 NewPath
= NewPath
[1:]
652 if not IsValidInstallPath(NewPath
):
653 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%NewPath
)
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')))
661 for MiscFile
in Module
.GetMiscFileList():
664 for Item
in MiscFile
.GetFileList():
666 if File
.startswith("\\") or File
.startswith("/"):
669 if not IsValidInstallPath(File
):
670 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%File
)
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
))
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("/"):
687 if not IsValidInstallPath(File
):
688 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%File
)
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
))
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("/"):
706 if not IsValidInstallPath(File
):
707 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%File
)
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
))
716 elif (ToFile
, Md5Sum
) not in Module
.FileList
:
717 Module
.FileList
.append((ToFile
, Md5Sum
))
719 InstallModuleContentZipFile(ContentZipFile
, FromPath
, ModulePath
, WorkspaceDir
, NewPath
, Module
, Package
, ReadOnly
,
722 ## InstallModuleContentZipFile
724 # InstallModuleContentZipFile
726 def InstallModuleContentZipFile(ContentZipFile
, FromPath
, ModulePath
, WorkspaceDir
, NewPath
, Module
, Package
, ReadOnly
,
729 # Extract other files under current module path in content Zip file but not listed in the description
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:]
739 if not IsValidInstallPath(FileName
):
740 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%FileName
)
743 ToFile
= os
.path
.normpath(os
.path
.join(WorkspaceDir
,
744 ConvertPath(FileName
.replace(FromPath
, NewPath
, 1))))
745 CheckList
= copy
.copy(Module
.FileList
)
747 CheckList
+= Package
.FileList
748 for Item
in CheckList
:
749 if Item
[0] == ToFile
:
752 Md5Sum
= InstallFile(ContentZipFile
, FromFile
, ToFile
, ReadOnly
)
753 if Package
and ((ToFile
, Md5Sum
) not in Package
.FileList
):
754 Package
.FileList
.append((ToFile
, Md5Sum
))
757 elif (ToFile
, Md5Sum
) not in Module
.FileList
:
758 Module
.FileList
.append((ToFile
, Md5Sum
))
760 ModuleList
.append((Module
, Package
))
763 # Check whether FileName started with directory specified by CheckPath
765 # @param FileName: the FileName need to be checked
766 # @param CheckPath: the path need to be checked against
767 # @return: True or False
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
)):
784 # Extract File from Zipfile, set file attribute, and return the Md5Sum
786 # @return: True or False
788 def InstallFile(ContentZipFile
, FromFile
, ToFile
, ReadOnly
, Executable
=False):
789 if os
.path
.exists(os
.path
.normpath(ToFile
)):
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
)
797 chmod(ToFile
, stat
.S_IRUSR | stat
.S_IRGRP | stat
.S_IROTH
)
799 chmod(ToFile
, stat
.S_IRUSR | stat
.S_IRGRP | stat
.S_IROTH | stat
.S_IEXEC | stat
.S_IXGRP | stat
.S_IXOTH
)
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
)
804 chmod(ToFile
, stat
.S_IRUSR | stat
.S_IRGRP | stat
.S_IROTH | stat
.S_IWUSR | stat
.S_IWGRP | stat
.S_IWOTH
)
806 Md5Sigature
= md5
.new(__FileHookOpen__(str(ToFile
), 'rb').read())
807 Md5Sum
= Md5Sigature
.hexdigest()
811 ## InstallPackageContent method
813 # @param FromPath: FromPath
814 # @param ToPath: ToPath
815 # @param Package: Package
816 # @param ContentZipFile: ContentZipFile
818 # @param WorkspaceDir: WorkspaceDir
819 # @param ModuleList: ModuleList
821 def InstallPackageContent(FromPath
, ToPath
, Package
, ContentZipFile
, Dep
,
822 WorkspaceDir
, ModuleList
, ReadOnly
= False):
825 Package
.FileList
= []
827 if ToPath
.startswith("\\") or ToPath
.startswith("/"):
830 if not IsValidInstallPath(ToPath
):
831 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%ToPath
)
833 if FromPath
.startswith("\\") or FromPath
.startswith("/"):
834 FromPath
= FromPath
[1:]
836 if not IsValidInstallPath(FromPath
):
837 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%FromPath
)
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:]
846 if not IsValidInstallPath(FileName
):
847 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%FileName
)
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:]
861 if not IsValidInstallPath(FileName
):
862 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%FileName
)
864 FromFile
= os
.path
.join(FromPath
, FileName
)
865 ToFile
= os
.path
.normpath(os
.path
.join(PackageFullPath
, ConvertPath(FileName
)))
866 RetFile
= ContentZipFile
.UnpackFile(FromFile
, ToFile
)
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
872 PackageIncludeArchList
.append([Item
.GetFilePath(), Item
.GetSupArchList()])
873 CreateDirectory(ToFile
)
876 chmod(ToFile
, stat
.S_IRUSR|stat
.S_IRGRP|stat
.S_IROTH
)
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
)
885 for Item
in Package
.GetStandardIncludeFileList():
886 FileName
= Item
.GetFilePath()
887 if FileName
.startswith("\\") or FileName
.startswith("/"):
888 FileName
= FileName
[1:]
890 if not IsValidInstallPath(FileName
):
891 Logger
.Error("UPT", FORMAT_INVALID
, ST
.ERR_FILE_NAME_INVALIDE
%FileName
)
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
))
902 Package
.SetPackagePath(Package
.GetPackagePath().replace(FromPath
,
904 Package
.SetFullPath(os
.path
.normpath(os
.path
.join(PackageFullPath
,
905 ConvertPath(Package
.GetName()) + '.dec')))
908 # Install files in module
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
)
919 # @param ZipFile: A ZipFile
921 def GetDPFile(ZipFile
):
924 for FileName
in ZipFile
.namelist():
925 if FileName
.endswith('.content'):
927 ContentFile
= FileName
929 elif FileName
.endswith('.pkg'):
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
945 # Install the distribution to current workspace
947 def InstallDp(DistPkg
, DpPkgFileName
, ContentZipFile
, Options
, Dep
, WorkspaceDir
, DataBase
):
949 # PackageList, ModuleList record the information for the meta-data
950 # files that need to be generated later
954 DistPkg
.PackageSurfaceArea
= GetPackageList(DistPkg
, Dep
, WorkspaceDir
, Options
,
955 ContentZipFile
, ModuleList
, PackageList
)
957 DistPkg
.ModuleSurfaceArea
= GetModuleList(DistPkg
, Dep
, WorkspaceDir
, ContentZipFile
, ModuleList
)
959 GenToolMisc(DistPkg
, WorkspaceDir
, ContentZipFile
)
962 # copy "Distribution File" to directory $(WORKSPACE)/conf/upt
964 DistFileName
= os
.path
.split(DpPkgFileName
)[1]
965 NewDpPkgFileName
= BackupDist(DpPkgFileName
, DistPkg
.Header
.GetGuid(), DistPkg
.Header
.GetVersion(), WorkspaceDir
)
970 Logger
.Quiet(ST
.MSG_UPDATE_PACKAGE_DATABASE
)
971 DataBase
.AddDPObject(DistPkg
, NewDpPkgFileName
, DistFileName
,
972 DistPkg
.Header
.RePackage
)