2 # This file is for installed package information database operations
4 # Copyright (c) 2011 - 2014, 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 a DP depex satisfied by current workspace
188 # (excluding the original distribution's packages to be replaced) for Replace
190 # @param DpObj: A distribution object
191 # @param OrigDpGuid: The original distribution's Guid
192 # @param OrigDpVersion: The original distribution's Version
194 def ReplaceCheckNewDpDepex(self
, DpObj
, OrigDpGuid
, OrigDpVersion
):
195 self
.PkgsToBeDepend
= [(PkgInfo
[1], PkgInfo
[2]) for PkgInfo
in self
.WsPkgList
]
196 OrigDpPackageList
= self
.IpiDb
.GetPackageListFromDp(OrigDpGuid
, OrigDpVersion
)
197 for OrigPkgInfo
in OrigDpPackageList
:
198 Guid
, Version
= OrigPkgInfo
[0], OrigPkgInfo
[1]
199 if (Guid
, Version
) in self
.PkgsToBeDepend
:
200 self
.PkgsToBeDepend
.remove((Guid
, Version
))
201 return self
.CheckDpDepexSatisfied(DpObj
)
203 ## Check whether a DP depex satisfied by current workspace.
205 # @param DpObj: A distribution object
207 def CheckDpDepexSatisfied(self
, DpObj
):
208 for PkgKey
in DpObj
.PackageSurfaceArea
.keys():
209 PkgObj
= DpObj
.PackageSurfaceArea
[PkgKey
]
210 if self
.CheckPackageDepexSatisfied(PkgObj
, DpObj
):
215 for ModKey
in DpObj
.ModuleSurfaceArea
.keys():
216 ModObj
= DpObj
.ModuleSurfaceArea
[ModKey
]
217 if self
.CheckModuleDepexSatisfied(ModObj
, DpObj
):
224 ## Check whether a DP could be removed from current workspace.
226 # @param DpGuid: File's guid
227 # @param DpVersion: File's version
228 # @retval Removable: True if distribution could be removed, False Else
229 # @retval DependModuleList: the list of modules that make distribution can not be removed
231 def CheckDpDepexForRemove(self
, DpGuid
, DpVersion
):
233 DependModuleList
= []
234 WsModuleList
= self
.WsModuleList
236 # remove modules that included in current DP
237 # List of item (FilePath)
238 DpModuleList
= self
.IpiDb
.GetDpModuleList(DpGuid
, DpVersion
)
239 for Module
in DpModuleList
:
240 if Module
in WsModuleList
:
241 WsModuleList
.remove(Module
)
244 ST
.ERR_MODULE_NOT_INSTALLED
% Module
)
246 # get packages in current Dp and find the install path
247 # List of item (PkgGuid, PkgVersion, InstallPath)
248 DpPackageList
= self
.IpiDb
.GetPackageListFromDp(DpGuid
, DpVersion
)
249 DpPackagePathList
= []
250 WorkSP
= GlobalData
.gWORKSPACE
251 for (PkgName
, PkgGuid
, PkgVersion
, DecFile
) in self
.WsPkgList
:
254 DecPath
= dirname(DecFile
)
255 if DecPath
.find(WorkSP
) > -1:
256 InstallPath
= GetRelativePath(DecPath
,WorkSP
)
257 DecFileRelaPath
= GetRelativePath(DecFile
,WorkSP
)
259 InstallPath
= DecPath
260 DecFileRelaPath
= DecFile
262 if (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
263 DpPackagePathList
.append(DecFileRelaPath
)
264 DpPackageList
.remove((PkgGuid
, PkgVersion
, InstallPath
))
267 # the left items in DpPackageList are the packages that installed but not found anymore
269 for (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
271 ST
.WARN_INSTALLED_PACKAGE_NOT_FOUND
%(PkgGuid
, PkgVersion
, InstallPath
))
274 # check modules to see if has dependency on package of current DP
276 for Module
in WsModuleList
:
277 if (not VerifyRemoveModuleDep(Module
, DpPackagePathList
)):
279 DependModuleList
.append(Module
)
280 return (Removable
, DependModuleList
)
283 ## Check whether a DP could be replaced by a distribution containing NewDpPkgList
284 # from current workspace.
286 # @param OrigDpGuid: original Dp's Guid
287 # @param OrigDpVersion: original Dp's version
288 # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp
289 # @retval Replaceable: True if distribution could be replaced, False Else
290 # @retval DependModuleList: the list of modules that make distribution can not be replaced
292 def CheckDpDepexForReplace(self
, OrigDpGuid
, OrigDpVersion
, NewDpPkgList
):
294 DependModuleList
= []
295 WsModuleList
= self
.WsModuleList
297 # remove modules that included in current DP
298 # List of item (FilePath)
299 DpModuleList
= self
.IpiDb
.GetDpModuleList(OrigDpGuid
, OrigDpVersion
)
300 for Module
in DpModuleList
:
301 if Module
in WsModuleList
:
302 WsModuleList
.remove(Module
)
305 ST
.ERR_MODULE_NOT_INSTALLED
% Module
)
307 OtherPkgList
= NewDpPkgList
309 # get packages in current Dp and find the install path
310 # List of item (PkgGuid, PkgVersion, InstallPath)
311 DpPackageList
= self
.IpiDb
.GetPackageListFromDp(OrigDpGuid
, OrigDpVersion
)
312 DpPackagePathList
= []
313 WorkSP
= GlobalData
.gWORKSPACE
314 for (PkgName
, PkgGuid
, PkgVersion
, DecFile
) in self
.WsPkgList
:
317 DecPath
= dirname(DecFile
)
318 if DecPath
.find(WorkSP
) > -1:
319 InstallPath
= GetRelativePath(DecPath
,WorkSP
)
320 DecFileRelaPath
= GetRelativePath(DecFile
,WorkSP
)
322 InstallPath
= DecPath
323 DecFileRelaPath
= DecFile
325 if (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
326 DpPackagePathList
.append(DecFileRelaPath
)
327 DpPackageList
.remove((PkgGuid
, PkgVersion
, InstallPath
))
329 OtherPkgList
.append((PkgGuid
, PkgVersion
))
332 # the left items in DpPackageList are the packages that installed but not found anymore
334 for (PkgGuid
, PkgVersion
, InstallPath
) in DpPackageList
:
336 ST
.WARN_INSTALLED_PACKAGE_NOT_FOUND
%(PkgGuid
, PkgVersion
, InstallPath
))
339 # check modules to see if it can be satisfied by package not belong to removed DP
341 for Module
in WsModuleList
:
342 if (not VerifyReplaceModuleDep(Module
, DpPackagePathList
, OtherPkgList
)):
344 DependModuleList
.append(Module
)
345 return (Replaceable
, DependModuleList
)
348 ## check whether module depends on packages in DpPackagePathList, return True
349 # if found, False else
351 # @param Path: a module path
352 # @param DpPackagePathList: a list of Package Paths
353 # @retval: False: module depends on package in DpPackagePathList
354 # True: module doesn't depend on package in DpPackagePathList
356 def VerifyRemoveModuleDep(Path
, DpPackagePathList
):
357 WorkSP
= GlobalData
.gWORKSPACE
360 PomAli
= InfPomAlignment(Path
, WorkSP
, Skip
=True)
362 for Item
in PomAli
.GetPackageDependencyList():
363 if Item
.GetPackageFilePath() in DpPackagePathList
:
364 Logger
.Info(ST
.MSG_MODULE_DEPEND_ON
% (Path
, Item
.GetPackageFilePath()))
368 except FatalError
, ErrCode
:
369 if ErrCode
.message
== EDK1_INF_ERROR
:
371 ST
.WRN_EDK1_INF_FOUND
%Path
)
376 ## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList
378 # @param Path: a module path
379 # @param DpPackagePathList: a list of Package Paths
380 # @param OtherPkgList: a list of Package Information (Guid, Version)
381 # @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList
382 # True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList
383 # but can be satisfied by OtherPkgList
385 def VerifyReplaceModuleDep(Path
, DpPackagePathList
, OtherPkgList
):
386 WorkSP
= GlobalData
.gWORKSPACE
389 PomAli
= InfPomAlignment(Path
, WorkSP
, Skip
=True)
391 for Item
in PomAli
.GetPackageDependencyList():
392 if Item
.GetPackageFilePath() in DpPackagePathList
:
393 Guid
, Version
= Item
.GetGuid(), Item
.GetVersion()
394 if (Guid
, Version
) not in OtherPkgList
:
395 Logger
.Info(ST
.MSG_MODULE_DEPEND_ON
% (Path
, Item
.GetPackageFilePath()))
399 except FatalError
, ErrCode
:
400 if ErrCode
.message
== EDK1_INF_ERROR
:
402 ST
.WRN_EDK1_INF_FOUND
%Path
)