]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Core/DependencyRules.py
BaseTools/Upt: Fix several bugs
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Core / DependencyRules.py
CommitLineData
4234283c
LG
1## @file\r
2# This file is for installed package information database operations\r
3#\r
421ccda3 4# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
4234283c
LG
5#\r
6# This program and the accompanying materials are licensed and made available \r
7# under the terms and conditions of the BSD License which accompanies this \r
8# distribution. The full text of the license may be found at \r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15\r
16'''\r
17Dependency\r
18'''\r
19\r
20##\r
21# Import Modules\r
22#\r
4234283c
LG
23from os.path import dirname\r
24\r
25import Logger.Log as Logger\r
26from Logger import StringTable as ST\r
27from Library.Parsing import GetWorkspacePackage\r
28from Library.Parsing import GetWorkspaceModule\r
421ccda3
HC
29from Library.Misc import GetRelativePath\r
30from Library import GlobalData\r
4234283c
LG
31from PomAdapter.InfPomAlignment import InfPomAlignment\r
32from Logger.ToolError import FatalError\r
33from Logger.ToolError import EDK1_INF_ERROR\r
34from Logger.ToolError import UNKNOWN_ERROR\r
35(DEPEX_CHECK_SUCCESS, DEPEX_CHECK_MODULE_NOT_FOUND, \\r
36DEPEX_CHECK_PACKAGE_NOT_FOUND, DEPEX_CHECK_DP_NOT_FOUND) = (0, 1, 2, 3)\r
37\r
38\r
421ccda3 39## DependencyRules\r
4234283c 40#\r
421ccda3 41# This class represents the dependency rule check mechanism\r
4234283c
LG
42# \r
43# @param object: Inherited from object class\r
44#\r
45class DependencyRules(object):\r
46 def __init__(self, Datab):\r
47 self.IpiDb = Datab\r
48 self.WsPkgList = GetWorkspacePackage()\r
49 self.WsModuleList = GetWorkspaceModule()\r
421ccda3
HC
50 self.PkgsToBeDepend = []\r
51 \r
52 ## Check whether a module exists by checking the Guid+Version+Name+Path combination\r
4234283c
LG
53 #\r
54 # @param Guid: Guid of a module\r
55 # @param Version: Version of a module\r
421ccda3
HC
56 # @param Name: Name of a module\r
57 # @param Path: Path of a module\r
58 # @return: True if module existed, else False\r
4234283c 59 #\r
421ccda3 60 def CheckModuleExists(self, Guid, Version, Name, Path):\r
4234283c 61 Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST)\r
d0acc87a
LG
62 ModuleList = self.IpiDb.GetModInPackage(Guid, Version, Name, Path)\r
63 ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version, Name, Path))\r
4234283c
LG
64 Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST_FINISH)\r
65 if len(ModuleList) > 0:\r
66 return True\r
67 else:\r
68 return False\r
69 \r
421ccda3 70 ## Check whether a module depex satisfied.\r
4234283c
LG
71 #\r
72 # @param ModuleObj: A module object\r
421ccda3
HC
73 # @param DpObj: A distribution object\r
74 # @return: True if module depex satisfied\r
75 # False else\r
4234283c 76 #\r
421ccda3 77 def CheckModuleDepexSatisfied(self, ModuleObj, DpObj=None):\r
4234283c
LG
78 Logger.Verbose(ST.MSG_CHECK_MODULE_DEPEX_START)\r
79 Result = True\r
80 Dep = None\r
81 if ModuleObj.GetPackageDependencyList():\r
82 Dep = ModuleObj.GetPackageDependencyList()[0]\r
83 for Dep in ModuleObj.GetPackageDependencyList():\r
84 #\r
85 # first check whether the dependency satisfied by current workspace\r
86 #\r
87 Exist = self.CheckPackageExists(Dep.GetGuid(), Dep.GetVersion())\r
88 #\r
89 # check whether satisfied by current distribution \r
90 #\r
91 if not Exist:\r
92 if DpObj == None:\r
93 Result = False\r
94 break\r
95 for GuidVerPair in DpObj.PackageSurfaceArea.keys():\r
96 if Dep.GetGuid() == GuidVerPair[0]:\r
97 if Dep.GetVersion() == None or \\r
98 len(Dep.GetVersion()) == 0:\r
99 Result = True\r
100 break\r
101 if Dep.GetVersion() == GuidVerPair[1]:\r
102 Result = True\r
103 break\r
104 else:\r
105 Result = False\r
106 break\r
107 \r
108 if not Result:\r
109 Logger.Error("CheckModuleDepex", UNKNOWN_ERROR, \\r
110 ST.ERR_DEPENDENCY_NOT_MATCH % (ModuleObj.GetName(), \\r
111 Dep.GetPackageFilePath(), \\r
112 Dep.GetGuid(), \\r
113 Dep.GetVersion()))\r
114 return Result\r
115 \r
421ccda3 116 ## Check whether a package exists in a package list specified by PkgsToBeDepend.\r
4234283c
LG
117 #\r
118 # @param Guid: Guid of a package\r
119 # @param Version: Version of a package\r
421ccda3
HC
120 # @return: True if package exist\r
121 # False else\r
4234283c
LG
122 #\r
123 def CheckPackageExists(self, Guid, Version):\r
124 Logger.Verbose(ST.MSG_CHECK_PACKAGE_START)\r
421ccda3
HC
125 Found = False\r
126 for (PkgGuid, PkgVer) in self.PkgsToBeDepend:\r
4234283c
LG
127 if (PkgGuid == Guid):\r
128 #\r
129 # if version is not empty and not equal, then not match\r
130 #\r
131 if Version and (PkgVer != Version):\r
421ccda3
HC
132 Found = False\r
133 break\r
4234283c 134 else:\r
421ccda3
HC
135 Found = True\r
136 break\r
4234283c 137 else:\r
421ccda3
HC
138 Found = False\r
139\r
4234283c 140 Logger.Verbose(ST.MSG_CHECK_PACKAGE_FINISH)\r
421ccda3 141 return Found\r
4234283c 142 \r
421ccda3 143 ## Check whether a package depex satisfied.\r
4234283c
LG
144 #\r
145 # @param PkgObj: A package object\r
421ccda3
HC
146 # @param DpObj: A distribution object\r
147 # @return: True if package depex satisified\r
148 # False else\r
4234283c 149 #\r
421ccda3 150 def CheckPackageDepexSatisfied(self, PkgObj, DpObj=None):\r
4234283c
LG
151 ModuleDict = PkgObj.GetModuleDict()\r
152 for ModKey in ModuleDict.keys():\r
153 ModObj = ModuleDict[ModKey]\r
421ccda3 154 if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
4234283c
LG
155 continue\r
156 else:\r
157 return False\r
158 return True\r
159 \r
421ccda3 160 ## Check whether a DP exists.\r
4234283c 161 #\r
421ccda3
HC
162 # @param Guid: Guid of a Distribution\r
163 # @param Version: Version of a Distribution\r
164 # @return: True if Distribution exist\r
165 # False else\r
166 def CheckDpExists(self, Guid, Version):\r
4234283c
LG
167 Logger.Verbose(ST.MSG_CHECK_DP_START)\r
168 DpList = self.IpiDb.GetDp(Guid, Version)\r
169 if len(DpList) > 0:\r
421ccda3 170 Found = True\r
4234283c 171 else:\r
421ccda3
HC
172 Found = False\r
173\r
174 Logger.Verbose(ST.MSG_CHECK_DP_FINISH)\r
175 return Found\r
176\r
177 ## Check whether a DP depex satisfied by current workspace for Install\r
178 #\r
179 # @param DpObj: A distribution object\r
180 # @return: True if distribution depex satisfied\r
181 # False else\r
182 #\r
183 def CheckInstallDpDepexSatisfied(self, DpObj):\r
184 self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
185 return self.CheckDpDepexSatisfied(DpObj)\r
186\r
187 ## Check whether a DP depex satisfied by current workspace \r
188 # (excluding the original distribution's packages to be replaced) for Replace\r
189 #\r
190 # @param DpObj: A distribution object\r
191 # @param OrigDpGuid: The original distribution's Guid\r
192 # @param OrigDpVersion: The original distribution's Version\r
193 #\r
194 def ReplaceCheckNewDpDepex(self, DpObj, OrigDpGuid, OrigDpVersion):\r
195 self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
196 OrigDpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion)\r
197 for OrigPkgInfo in OrigDpPackageList:\r
198 Guid, Version = OrigPkgInfo[0], OrigPkgInfo[1]\r
199 if (Guid, Version) in self.PkgsToBeDepend:\r
200 self.PkgsToBeDepend.remove((Guid, Version))\r
201 return self.CheckDpDepexSatisfied(DpObj)\r
202\r
4234283c
LG
203 ## Check whether a DP depex satisfied by current workspace.\r
204 #\r
421ccda3 205 # @param DpObj: A distribution object\r
4234283c 206 #\r
421ccda3 207 def CheckDpDepexSatisfied(self, DpObj):\r
4234283c
LG
208 for PkgKey in DpObj.PackageSurfaceArea.keys():\r
209 PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
421ccda3 210 if self.CheckPackageDepexSatisfied(PkgObj, DpObj):\r
4234283c
LG
211 continue\r
212 else:\r
213 return False\r
214 \r
215 for ModKey in DpObj.ModuleSurfaceArea.keys():\r
216 ModObj = DpObj.ModuleSurfaceArea[ModKey]\r
421ccda3 217 if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
4234283c
LG
218 continue\r
219 else:\r
220 return False\r
221 \r
222 return True\r
223 \r
421ccda3 224 ## Check whether a DP could be removed from current workspace. \r
4234283c
LG
225 #\r
226 # @param DpGuid: File's guid\r
227 # @param DpVersion: File's version\r
421ccda3
HC
228 # @retval Removable: True if distribution could be removed, False Else\r
229 # @retval DependModuleList: the list of modules that make distribution can not be removed\r
230 #\r
231 def CheckDpDepexForRemove(self, DpGuid, DpVersion):\r
4234283c
LG
232 Removable = True\r
233 DependModuleList = []\r
234 WsModuleList = self.WsModuleList\r
235 #\r
236 # remove modules that included in current DP\r
237 # List of item (FilePath)\r
238 DpModuleList = self.IpiDb.GetDpModuleList(DpGuid, DpVersion) \r
239 for Module in DpModuleList:\r
240 if Module in WsModuleList:\r
241 WsModuleList.remove(Module)\r
242 else:\r
243 Logger.Warn("UPT\n",\r
244 ST.ERR_MODULE_NOT_INSTALLED % Module)\r
245 #\r
246 # get packages in current Dp and find the install path\r
247 # List of item (PkgGuid, PkgVersion, InstallPath)\r
248 DpPackageList = self.IpiDb.GetPackageListFromDp(DpGuid, DpVersion) \r
249 DpPackagePathList = []\r
421ccda3 250 WorkSP = GlobalData.gWORKSPACE\r
4234283c
LG
251 for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
252 if PkgName:\r
253 pass\r
254 DecPath = dirname(DecFile)\r
255 if DecPath.find(WorkSP) > -1:\r
421ccda3
HC
256 InstallPath = GetRelativePath(DecPath,WorkSP)\r
257 DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
4234283c
LG
258 else:\r
259 InstallPath = DecPath\r
260 DecFileRelaPath = DecFile\r
261 \r
262 if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
263 DpPackagePathList.append(DecFileRelaPath)\r
264 DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
265 \r
266 #\r
267 # the left items in DpPackageList are the packages that installed but not found anymore\r
268 #\r
269 for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
270 Logger.Warn("UPT",\r
271 ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
272 \r
273 #\r
274 # check modules to see if has dependency on package of current DP\r
275 #\r
276 for Module in WsModuleList:\r
421ccda3 277 if (not VerifyRemoveModuleDep(Module, DpPackagePathList)):\r
4234283c
LG
278 Removable = False\r
279 DependModuleList.append(Module)\r
280 return (Removable, DependModuleList)\r
281\r
282\r
421ccda3
HC
283 ## Check whether a DP could be replaced by a distribution containing NewDpPkgList\r
284 # from current workspace.\r
285 #\r
286 # @param OrigDpGuid: original Dp's Guid\r
287 # @param OrigDpVersion: original Dp's version\r
288 # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp\r
289 # @retval Replaceable: True if distribution could be replaced, False Else\r
290 # @retval DependModuleList: the list of modules that make distribution can not be replaced\r
291 # \r
292 def CheckDpDepexForReplace(self, OrigDpGuid, OrigDpVersion, NewDpPkgList):\r
293 Replaceable = True\r
294 DependModuleList = []\r
295 WsModuleList = self.WsModuleList\r
296 #\r
297 # remove modules that included in current DP\r
298 # List of item (FilePath)\r
299 DpModuleList = self.IpiDb.GetDpModuleList(OrigDpGuid, OrigDpVersion) \r
300 for Module in DpModuleList:\r
301 if Module in WsModuleList:\r
302 WsModuleList.remove(Module)\r
303 else:\r
304 Logger.Warn("UPT\n",\r
305 ST.ERR_MODULE_NOT_INSTALLED % Module)\r
306 \r
307 OtherPkgList = NewDpPkgList\r
308 #\r
309 # get packages in current Dp and find the install path\r
310 # List of item (PkgGuid, PkgVersion, InstallPath)\r
311 DpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion) \r
312 DpPackagePathList = []\r
313 WorkSP = GlobalData.gWORKSPACE\r
314 for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
315 if PkgName:\r
316 pass\r
317 DecPath = dirname(DecFile)\r
318 if DecPath.find(WorkSP) > -1:\r
319 InstallPath = GetRelativePath(DecPath,WorkSP)\r
320 DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
321 else:\r
322 InstallPath = DecPath\r
323 DecFileRelaPath = DecFile\r
324 \r
325 if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
326 DpPackagePathList.append(DecFileRelaPath)\r
327 DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
328 else:\r
329 OtherPkgList.append((PkgGuid, PkgVersion))\r
330\r
331 #\r
332 # the left items in DpPackageList are the packages that installed but not found anymore\r
333 #\r
334 for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
335 Logger.Warn("UPT",\r
336 ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
337 \r
338 #\r
339 # check modules to see if it can be satisfied by package not belong to removed DP\r
340 #\r
341 for Module in WsModuleList:\r
342 if (not VerifyReplaceModuleDep(Module, DpPackagePathList, OtherPkgList)):\r
343 Replaceable = False\r
344 DependModuleList.append(Module)\r
345 return (Replaceable, DependModuleList)\r
346\r
347 \r
4234283c
LG
348## check whether module depends on packages in DpPackagePathList, return True \r
349# if found, False else\r
350#\r
351# @param Path: a module path\r
352# @param DpPackagePathList: a list of Package Paths\r
421ccda3
HC
353# @retval: False: module depends on package in DpPackagePathList\r
354# True: module doesn't depend on package in DpPackagePathList\r
4234283c 355#\r
421ccda3
HC
356def VerifyRemoveModuleDep(Path, DpPackagePathList):\r
357 WorkSP = GlobalData.gWORKSPACE\r
4234283c
LG
358 \r
359 try:\r
360 PomAli = InfPomAlignment(Path, WorkSP, Skip=True)\r
361\r
362 for Item in PomAli.GetPackageDependencyList():\r
363 if Item.GetPackageFilePath() in DpPackagePathList:\r
364 Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, Item.GetPackageFilePath()))\r
421ccda3 365 return False\r
4234283c 366 else:\r
421ccda3 367 return True\r
4234283c
LG
368 except FatalError, ErrCode:\r
369 if ErrCode.message == EDK1_INF_ERROR:\r
370 Logger.Warn("UPT",\r
371 ST.WRN_EDK1_INF_FOUND%Path)\r
421ccda3 372 return True\r
4234283c 373 else:\r
421ccda3
HC
374 return True\r
375\r
376## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList\r
377#\r
378# @param Path: a module path\r
379# @param DpPackagePathList: a list of Package Paths\r
380# @param OtherPkgList: a list of Package Information (Guid, Version)\r
381# @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList\r
382# True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList \r
383# but can be satisfied by OtherPkgList\r
384#\r
385def VerifyReplaceModuleDep(Path, DpPackagePathList, OtherPkgList):\r
386 WorkSP = GlobalData.gWORKSPACE\r
387 \r
388 try:\r
389 PomAli = InfPomAlignment(Path, WorkSP, Skip=True)\r
390\r
391 for Item in PomAli.GetPackageDependencyList():\r
392 if Item.GetPackageFilePath() in DpPackagePathList:\r
393 Guid, Version = Item.GetGuid(), Item.GetVersion()\r
394 if (Guid, Version) not in OtherPkgList:\r
395 Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, Item.GetPackageFilePath()))\r
396 return False\r
397 else:\r
398 return True\r
399 except FatalError, ErrCode:\r
400 if ErrCode.message == EDK1_INF_ERROR:\r
401 Logger.Warn("UPT",\r
402 ST.WRN_EDK1_INF_FOUND%Path)\r
403 return True\r
404 else:\r
405 return True\r
406 \r
4234283c
LG
407\r
408\r