]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Core/DependencyRules.py
BaseTool/UPT: Add Test Install
[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
6cf99034 4# Copyright (c) 2011 - 2016, 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
6cf99034
HC
187 # # Check whether multiple DP depex satisfied by current workspace for Install\r
188 #\r
189 # @param DpObjList: A distribution object list\r
190 # @return: True if distribution depex satisfied\r
191 # False else\r
192 #\r
193 def CheckTestInstallPdDepexSatisfied(self, DpObjList):\r
194 self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
195 for DpObj in DpObjList:\r
196 if self.CheckDpDepexSatisfied(DpObj):\r
197 for PkgKey in DpObj.PackageSurfaceArea.keys():\r
198 PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
199 self.PkgsToBeDepend.append((PkgObj.Guid, PkgObj.Version))\r
200 else:\r
201 return False, DpObj\r
202\r
203 return True, DpObj\r
204\r
205\r
421ccda3
HC
206 ## Check whether a DP depex satisfied by current workspace \r
207 # (excluding the original distribution's packages to be replaced) for Replace\r
208 #\r
209 # @param DpObj: A distribution object\r
210 # @param OrigDpGuid: The original distribution's Guid\r
211 # @param OrigDpVersion: The original distribution's Version\r
212 #\r
213 def ReplaceCheckNewDpDepex(self, DpObj, OrigDpGuid, OrigDpVersion):\r
214 self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
215 OrigDpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion)\r
216 for OrigPkgInfo in OrigDpPackageList:\r
217 Guid, Version = OrigPkgInfo[0], OrigPkgInfo[1]\r
218 if (Guid, Version) in self.PkgsToBeDepend:\r
219 self.PkgsToBeDepend.remove((Guid, Version))\r
220 return self.CheckDpDepexSatisfied(DpObj)\r
221\r
4234283c
LG
222 ## Check whether a DP depex satisfied by current workspace.\r
223 #\r
421ccda3 224 # @param DpObj: A distribution object\r
4234283c 225 #\r
421ccda3 226 def CheckDpDepexSatisfied(self, DpObj):\r
4234283c
LG
227 for PkgKey in DpObj.PackageSurfaceArea.keys():\r
228 PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
421ccda3 229 if self.CheckPackageDepexSatisfied(PkgObj, DpObj):\r
4234283c
LG
230 continue\r
231 else:\r
232 return False\r
233 \r
234 for ModKey in DpObj.ModuleSurfaceArea.keys():\r
235 ModObj = DpObj.ModuleSurfaceArea[ModKey]\r
421ccda3 236 if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
4234283c
LG
237 continue\r
238 else:\r
239 return False\r
240 \r
241 return True\r
242 \r
421ccda3 243 ## Check whether a DP could be removed from current workspace. \r
4234283c
LG
244 #\r
245 # @param DpGuid: File's guid\r
246 # @param DpVersion: File's version\r
421ccda3
HC
247 # @retval Removable: True if distribution could be removed, False Else\r
248 # @retval DependModuleList: the list of modules that make distribution can not be removed\r
249 #\r
250 def CheckDpDepexForRemove(self, DpGuid, DpVersion):\r
4234283c
LG
251 Removable = True\r
252 DependModuleList = []\r
253 WsModuleList = self.WsModuleList\r
254 #\r
255 # remove modules that included in current DP\r
256 # List of item (FilePath)\r
257 DpModuleList = self.IpiDb.GetDpModuleList(DpGuid, DpVersion) \r
258 for Module in DpModuleList:\r
259 if Module in WsModuleList:\r
260 WsModuleList.remove(Module)\r
261 else:\r
262 Logger.Warn("UPT\n",\r
263 ST.ERR_MODULE_NOT_INSTALLED % Module)\r
264 #\r
265 # get packages in current Dp and find the install path\r
266 # List of item (PkgGuid, PkgVersion, InstallPath)\r
267 DpPackageList = self.IpiDb.GetPackageListFromDp(DpGuid, DpVersion) \r
268 DpPackagePathList = []\r
421ccda3 269 WorkSP = GlobalData.gWORKSPACE\r
4234283c
LG
270 for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
271 if PkgName:\r
272 pass\r
273 DecPath = dirname(DecFile)\r
274 if DecPath.find(WorkSP) > -1:\r
421ccda3
HC
275 InstallPath = GetRelativePath(DecPath,WorkSP)\r
276 DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
4234283c
LG
277 else:\r
278 InstallPath = DecPath\r
279 DecFileRelaPath = DecFile\r
280 \r
281 if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
282 DpPackagePathList.append(DecFileRelaPath)\r
283 DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
284 \r
285 #\r
286 # the left items in DpPackageList are the packages that installed but not found anymore\r
287 #\r
288 for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
289 Logger.Warn("UPT",\r
290 ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
291 \r
292 #\r
293 # check modules to see if has dependency on package of current DP\r
294 #\r
295 for Module in WsModuleList:\r
421ccda3 296 if (not VerifyRemoveModuleDep(Module, DpPackagePathList)):\r
4234283c
LG
297 Removable = False\r
298 DependModuleList.append(Module)\r
299 return (Removable, DependModuleList)\r
300\r
301\r
421ccda3
HC
302 ## Check whether a DP could be replaced by a distribution containing NewDpPkgList\r
303 # from current workspace.\r
304 #\r
305 # @param OrigDpGuid: original Dp's Guid\r
306 # @param OrigDpVersion: original Dp's version\r
307 # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp\r
308 # @retval Replaceable: True if distribution could be replaced, False Else\r
309 # @retval DependModuleList: the list of modules that make distribution can not be replaced\r
310 # \r
311 def CheckDpDepexForReplace(self, OrigDpGuid, OrigDpVersion, NewDpPkgList):\r
312 Replaceable = True\r
313 DependModuleList = []\r
314 WsModuleList = self.WsModuleList\r
315 #\r
316 # remove modules that included in current DP\r
317 # List of item (FilePath)\r
318 DpModuleList = self.IpiDb.GetDpModuleList(OrigDpGuid, OrigDpVersion) \r
319 for Module in DpModuleList:\r
320 if Module in WsModuleList:\r
321 WsModuleList.remove(Module)\r
322 else:\r
323 Logger.Warn("UPT\n",\r
324 ST.ERR_MODULE_NOT_INSTALLED % Module)\r
325 \r
326 OtherPkgList = NewDpPkgList\r
327 #\r
328 # get packages in current Dp and find the install path\r
329 # List of item (PkgGuid, PkgVersion, InstallPath)\r
330 DpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion) \r
331 DpPackagePathList = []\r
332 WorkSP = GlobalData.gWORKSPACE\r
333 for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
334 if PkgName:\r
335 pass\r
336 DecPath = dirname(DecFile)\r
337 if DecPath.find(WorkSP) > -1:\r
338 InstallPath = GetRelativePath(DecPath,WorkSP)\r
339 DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
340 else:\r
341 InstallPath = DecPath\r
342 DecFileRelaPath = DecFile\r
343 \r
344 if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
345 DpPackagePathList.append(DecFileRelaPath)\r
346 DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
347 else:\r
348 OtherPkgList.append((PkgGuid, PkgVersion))\r
349\r
350 #\r
351 # the left items in DpPackageList are the packages that installed but not found anymore\r
352 #\r
353 for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
354 Logger.Warn("UPT",\r
355 ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
356 \r
357 #\r
358 # check modules to see if it can be satisfied by package not belong to removed DP\r
359 #\r
360 for Module in WsModuleList:\r
361 if (not VerifyReplaceModuleDep(Module, DpPackagePathList, OtherPkgList)):\r
362 Replaceable = False\r
363 DependModuleList.append(Module)\r
364 return (Replaceable, DependModuleList)\r
365\r
366 \r
4234283c
LG
367## check whether module depends on packages in DpPackagePathList, return True \r
368# if found, False else\r
369#\r
370# @param Path: a module path\r
371# @param DpPackagePathList: a list of Package Paths\r
421ccda3
HC
372# @retval: False: module depends on package in DpPackagePathList\r
373# True: module doesn't depend on package in DpPackagePathList\r
4234283c 374#\r
421ccda3
HC
375def VerifyRemoveModuleDep(Path, DpPackagePathList):\r
376 WorkSP = GlobalData.gWORKSPACE\r
4234283c
LG
377 \r
378 try:\r
379 PomAli = InfPomAlignment(Path, WorkSP, Skip=True)\r
380\r
381 for Item in PomAli.GetPackageDependencyList():\r
382 if Item.GetPackageFilePath() in DpPackagePathList:\r
383 Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, Item.GetPackageFilePath()))\r
421ccda3 384 return False\r
4234283c 385 else:\r
421ccda3 386 return True\r
4234283c
LG
387 except FatalError, ErrCode:\r
388 if ErrCode.message == EDK1_INF_ERROR:\r
389 Logger.Warn("UPT",\r
390 ST.WRN_EDK1_INF_FOUND%Path)\r
421ccda3 391 return True\r
4234283c 392 else:\r
421ccda3
HC
393 return True\r
394\r
395## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList\r
396#\r
397# @param Path: a module path\r
398# @param DpPackagePathList: a list of Package Paths\r
399# @param OtherPkgList: a list of Package Information (Guid, Version)\r
400# @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList\r
401# True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList \r
402# but can be satisfied by OtherPkgList\r
403#\r
404def VerifyReplaceModuleDep(Path, DpPackagePathList, OtherPkgList):\r
405 WorkSP = GlobalData.gWORKSPACE\r
406 \r
407 try:\r
408 PomAli = InfPomAlignment(Path, WorkSP, Skip=True)\r
409\r
410 for Item in PomAli.GetPackageDependencyList():\r
411 if Item.GetPackageFilePath() in DpPackagePathList:\r
412 Guid, Version = Item.GetGuid(), Item.GetVersion()\r
413 if (Guid, Version) not in OtherPkgList:\r
414 Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, Item.GetPackageFilePath()))\r
415 return False\r
416 else:\r
417 return True\r
418 except FatalError, ErrCode:\r
419 if ErrCode.message == EDK1_INF_ERROR:\r
420 Logger.Warn("UPT",\r
421 ST.WRN_EDK1_INF_FOUND%Path)\r
422 return True\r
423 else:\r
424 return True\r
425 \r
4234283c
LG
426\r
427\r