2 # This file is for installed package information database operations
4 # Copyright (c) 2011 - 2016, 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
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 from os
.path
import dirname
25 import Logger
.Log
as Logger
26 from Logger
import StringTable
as ST
27 from Library
.Parsing
import GetWorkspacePackage
28 from Library
.Parsing
import GetWorkspaceModule
29 from Library
.Misc
import GetRelativePath
30 from Library
import GlobalData
31 from PomAdapter
.InfPomAlignment
import InfPomAlignment
32 from Logger
.ToolError
import FatalError
33 from Logger
.ToolError
import EDK1_INF_ERROR
34 from Logger
.ToolError
import UNKNOWN_ERROR
35 (DEPEX_CHECK_SUCCESS
, DEPEX_CHECK_MODULE_NOT_FOUND
, \
36 DEPEX_CHECK_PACKAGE_NOT_FOUND
, DEPEX_CHECK_DP_NOT_FOUND
) = (0, 1, 2, 3)
41 # This class represents the dependency rule check mechanism
43 # @param object: Inherited from object class
45 class DependencyRules(object):
46 def __init__(self
, Datab
):
48 self
.WsPkgList
= GetWorkspacePackage()
49 self
.WsModuleList
= GetWorkspaceModule()
50 self
.PkgsToBeDepend
= []
52 ## Check whether a module exists by checking the Guid+Version+Name+Path combination
54 # @param Guid: Guid of a module
55 # @param Version: Version of a module
56 # @param Name: Name of a module
57 # @param Path: Path of a module
58 # @return: True if module existed, else False
60 def CheckModuleExists(self
, Guid
, Version
, Name
, Path
):
61 Logger
.Verbose(ST
.MSG_CHECK_MODULE_EXIST
)
62 ModuleList
= self
.IpiDb
.GetModInPackage(Guid
, Version
, Name
, Path
)
63 ModuleList
.extend(self
.IpiDb
.GetStandaloneModule(Guid
, Version
, Name
, Path
))
64 Logger
.Verbose(ST
.MSG_CHECK_MODULE_EXIST_FINISH
)
65 if len(ModuleList
) > 0:
70 ## Check whether a module depex satisfied.
72 # @param ModuleObj: A module object
73 # @param DpObj: A distribution object
74 # @return: True if module depex satisfied
77 def CheckModuleDepexSatisfied(self
, ModuleObj
, DpObj
=None):
78 Logger
.Verbose(ST
.MSG_CHECK_MODULE_DEPEX_START
)
81 if ModuleObj
.GetPackageDependencyList():
82 Dep
= ModuleObj
.GetPackageDependencyList()[0]
83 for Dep
in ModuleObj
.GetPackageDependencyList():
85 # first check whether the dependency satisfied by current workspace
87 Exist
= self
.CheckPackageExists(Dep
.GetGuid(), Dep
.GetVersion())
89 # check whether satisfied by current distribution
95 for GuidVerPair
in DpObj
.PackageSurfaceArea
.keys():
96 if Dep
.GetGuid() == GuidVerPair
[0]:
97 if Dep
.GetVersion() == None or \
98 len(Dep
.GetVersion()) == 0:
101 if Dep
.GetVersion() == GuidVerPair
[1]:
109 Logger
.Error("CheckModuleDepex", UNKNOWN_ERROR
, \
110 ST
.ERR_DEPENDENCY_NOT_MATCH
% (ModuleObj
.GetName(), \
111 Dep
.GetPackageFilePath(), \
116 ## Check whether a package exists in a package list specified by PkgsToBeDepend.
118 # @param Guid: Guid of a package
119 # @param Version: Version of a package
120 # @return: True if package exist
123 def CheckPackageExists(self
, Guid
, Version
):
124 Logger
.Verbose(ST
.MSG_CHECK_PACKAGE_START
)
126 for (PkgGuid
, PkgVer
) in self
.PkgsToBeDepend
:
127 if (PkgGuid
== Guid
):
129 # if version is not empty and not equal, then not match
131 if Version
and (PkgVer
!= Version
):
140 Logger
.Verbose(ST
.MSG_CHECK_PACKAGE_FINISH
)
143 ## Check whether a package depex satisfied.
145 # @param PkgObj: A package object
146 # @param DpObj: A distribution object
147 # @return: True if package depex satisified
150 def CheckPackageDepexSatisfied(self
, PkgObj
, DpObj
=None):
151 ModuleDict
= PkgObj
.GetModuleDict()
152 for ModKey
in ModuleDict
.keys():
153 ModObj
= ModuleDict
[ModKey
]
154 if self
.CheckModuleDepexSatisfied(ModObj
, DpObj
):
160 ## Check whether a DP exists.
162 # @param Guid: Guid of a Distribution
163 # @param Version: Version of a Distribution
164 # @return: True if Distribution exist
166 def CheckDpExists(self
, Guid
, Version
):
167 Logger
.Verbose(ST
.MSG_CHECK_DP_START
)
168 DpList
= self
.IpiDb
.GetDp(Guid
, Version
)
174 Logger
.Verbose(ST
.MSG_CHECK_DP_FINISH
)
177 ## Check whether a DP depex satisfied by current workspace for Install
179 # @param DpObj: A distribution object
180 # @return: True if distribution depex satisfied
183 def CheckInstallDpDepexSatisfied(self
, DpObj
):
184 self
.PkgsToBeDepend
= [(PkgInfo
[1], PkgInfo
[2]) for PkgInfo
in self
.WsPkgList
]
185 return self
.CheckDpDepexSatisfied(DpObj
)
187 # # Check whether multiple DP depex satisfied by current workspace for Install
189 # @param DpObjList: A distribution object list
190 # @return: True if distribution depex satisfied
193 def CheckTestInstallPdDepexSatisfied(self
, DpObjList
):
194 self
.PkgsToBeDepend
= [(PkgInfo
[1], PkgInfo
[2]) for PkgInfo
in self
.WsPkgList
]
195 for DpObj
in DpObjList
:
196 if self
.CheckDpDepexSatisfied(DpObj
):
197 for PkgKey
in DpObj
.PackageSurfaceArea
.keys():
198 PkgObj
= DpObj
.PackageSurfaceArea
[PkgKey
]
199 self
.PkgsToBeDepend
.append((PkgObj
.Guid
, PkgObj
.Version
))
206 ## Check whether a DP depex satisfied by current workspace
207 # (excluding the original distribution's packages to be replaced) for Replace
209 # @param DpObj: A distribution object
210 # @param OrigDpGuid: The original distribution's Guid
211 # @param OrigDpVersion: The original distribution's Version
213 def ReplaceCheckNewDpDepex(self
, DpObj
, OrigDpGuid
, OrigDpVersion
):
214 self
.PkgsToBeDepend
= [(PkgInfo
[1], PkgInfo
[2]) for PkgInfo
in self
.WsPkgList
]
215 OrigDpPackageList
= self
.IpiDb
.GetPackageListFromDp(OrigDpGuid
, OrigDpVersion
)
216 for OrigPkgInfo
in OrigDpPackageList
:
217 Guid
, Version
= OrigPkgInfo
[0], OrigPkgInfo
[1]
218 if (Guid
, Version
) in self
.PkgsToBeDepend
:
219 self
.PkgsToBeDepend
.remove((Guid
, Version
))
220 return self
.CheckDpDepexSatisfied(DpObj
)
222 ## Check whether a DP depex satisfied by current workspace.
224 # @param DpObj: A distribution object
226 def CheckDpDepexSatisfied(self
, DpObj
):
227 for PkgKey
in DpObj
.PackageSurfaceArea
.keys():
228 PkgObj
= DpObj
.PackageSurfaceArea
[PkgKey
]
229 if self
.CheckPackageDepexSatisfied(PkgObj
, DpObj
):
234 for ModKey
in DpObj
.ModuleSurfaceArea
.keys():
235 ModObj
= DpObj
.ModuleSurfaceArea
[ModKey
]
236 if self
.CheckModuleDepexSatisfied(ModObj
, DpObj
):
243 ## Check whether a DP could be removed from current workspace.
245 # @param DpGuid: File's guid
246 # @param DpVersion: File's version
247 # @retval Removable: True if distribution could be removed, False Else
248 # @retval DependModuleList: the list of modules that make distribution can not be removed
250 def CheckDpDepexForRemove(self
, DpGuid
, DpVersion
):
252 DependModuleList
= []
253 WsModuleList
= self
.WsModuleList
255 # remove modules that included in current DP
256 # List of item (FilePath)
257 DpModuleList
= self
.IpiDb
.GetDpModuleList(DpGuid
, DpVersion
)
258 for Module
in DpModuleList
:
259 if Module
in WsModuleList
:
260 WsModuleList
.remove(Module
)
263 ST
.ERR_MODULE_NOT_INSTALLED
% Module
)
265 # get packages in current Dp and find the install path
266 # List of item (PkgGuid, PkgVersion, InstallPath)
267 DpPackageList
= self
.IpiDb
.GetPackageListFromDp(DpGuid
, DpVersion
)
268 DpPackagePathList
= []
269 WorkSP
= GlobalData
.gWORKSPACE
270 for (PkgName
, PkgGuid
, PkgVersion
, DecFile
) in self
.WsPkgList
:
273 DecPath
= dirname(DecFile
)
274 if DecPath
.find(WorkSP
) > -1:
275 InstallPath
= GetRelativePath(DecPath
,WorkSP
)
276 DecFileRelaPath
= GetRelativePath(DecFile
,WorkSP
)
278 InstallPath
= DecPath
279 DecFileRelaPath
= DecFile
281 if (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
282 DpPackagePathList
.append(DecFileRelaPath
)
283 DpPackageList
.remove((PkgGuid
, PkgVersion
, InstallPath
))
286 # the left items in DpPackageList are the packages that installed but not found anymore
288 for (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
290 ST
.WARN_INSTALLED_PACKAGE_NOT_FOUND
%(PkgGuid
, PkgVersion
, InstallPath
))
293 # check modules to see if has dependency on package of current DP
295 for Module
in WsModuleList
:
296 if (not VerifyRemoveModuleDep(Module
, DpPackagePathList
)):
298 DependModuleList
.append(Module
)
299 return (Removable
, DependModuleList
)
302 ## Check whether a DP could be replaced by a distribution containing NewDpPkgList
303 # from current workspace.
305 # @param OrigDpGuid: original Dp's Guid
306 # @param OrigDpVersion: original Dp's version
307 # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp
308 # @retval Replaceable: True if distribution could be replaced, False Else
309 # @retval DependModuleList: the list of modules that make distribution can not be replaced
311 def CheckDpDepexForReplace(self
, OrigDpGuid
, OrigDpVersion
, NewDpPkgList
):
313 DependModuleList
= []
314 WsModuleList
= self
.WsModuleList
316 # remove modules that included in current DP
317 # List of item (FilePath)
318 DpModuleList
= self
.IpiDb
.GetDpModuleList(OrigDpGuid
, OrigDpVersion
)
319 for Module
in DpModuleList
:
320 if Module
in WsModuleList
:
321 WsModuleList
.remove(Module
)
324 ST
.ERR_MODULE_NOT_INSTALLED
% Module
)
326 OtherPkgList
= NewDpPkgList
328 # get packages in current Dp and find the install path
329 # List of item (PkgGuid, PkgVersion, InstallPath)
330 DpPackageList
= self
.IpiDb
.GetPackageListFromDp(OrigDpGuid
, OrigDpVersion
)
331 DpPackagePathList
= []
332 WorkSP
= GlobalData
.gWORKSPACE
333 for (PkgName
, PkgGuid
, PkgVersion
, DecFile
) in self
.WsPkgList
:
336 DecPath
= dirname(DecFile
)
337 if DecPath
.find(WorkSP
) > -1:
338 InstallPath
= GetRelativePath(DecPath
,WorkSP
)
339 DecFileRelaPath
= GetRelativePath(DecFile
,WorkSP
)
341 InstallPath
= DecPath
342 DecFileRelaPath
= DecFile
344 if (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
345 DpPackagePathList
.append(DecFileRelaPath
)
346 DpPackageList
.remove((PkgGuid
, PkgVersion
, InstallPath
))
348 OtherPkgList
.append((PkgGuid
, PkgVersion
))
351 # the left items in DpPackageList are the packages that installed but not found anymore
353 for (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
355 ST
.WARN_INSTALLED_PACKAGE_NOT_FOUND
%(PkgGuid
, PkgVersion
, InstallPath
))
358 # check modules to see if it can be satisfied by package not belong to removed DP
360 for Module
in WsModuleList
:
361 if (not VerifyReplaceModuleDep(Module
, DpPackagePathList
, OtherPkgList
)):
363 DependModuleList
.append(Module
)
364 return (Replaceable
, DependModuleList
)
367 ## check whether module depends on packages in DpPackagePathList, return True
368 # if found, False else
370 # @param Path: a module path
371 # @param DpPackagePathList: a list of Package Paths
372 # @retval: False: module depends on package in DpPackagePathList
373 # True: module doesn't depend on package in DpPackagePathList
375 def VerifyRemoveModuleDep(Path
, DpPackagePathList
):
376 WorkSP
= GlobalData
.gWORKSPACE
379 PomAli
= InfPomAlignment(Path
, WorkSP
, Skip
=True)
381 for Item
in PomAli
.GetPackageDependencyList():
382 if Item
.GetPackageFilePath() in DpPackagePathList
:
383 Logger
.Info(ST
.MSG_MODULE_DEPEND_ON
% (Path
, Item
.GetPackageFilePath()))
387 except FatalError
, ErrCode
:
388 if ErrCode
.message
== EDK1_INF_ERROR
:
390 ST
.WRN_EDK1_INF_FOUND
%Path
)
395 ## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList
397 # @param Path: a module path
398 # @param DpPackagePathList: a list of Package Paths
399 # @param OtherPkgList: a list of Package Information (Guid, Version)
400 # @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList
401 # True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList
402 # but can be satisfied by OtherPkgList
404 def VerifyReplaceModuleDep(Path
, DpPackagePathList
, OtherPkgList
):
405 WorkSP
= GlobalData
.gWORKSPACE
408 PomAli
= InfPomAlignment(Path
, WorkSP
, Skip
=True)
410 for Item
in PomAli
.GetPackageDependencyList():
411 if Item
.GetPackageFilePath() in DpPackagePathList
:
412 Guid
, Version
= Item
.GetGuid(), Item
.GetVersion()
413 if (Guid
, Version
) not in OtherPkgList
:
414 Logger
.Info(ST
.MSG_MODULE_DEPEND_ON
% (Path
, Item
.GetPackageFilePath()))
418 except FatalError
, ErrCode
:
419 if ErrCode
.message
== EDK1_INF_ERROR
:
421 ST
.WRN_EDK1_INF_FOUND
%Path
)