]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/UPT/Core/DependencyRules.py
BaseTools: Refactor python except statements
[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
5692fa88 4# Copyright (c) 2011 - 2017, 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 23from os.path import dirname\r
5692fa88 24import os\r
4234283c
LG
25\r
26import Logger.Log as Logger\r
27from Logger import StringTable as ST\r
28from Library.Parsing import GetWorkspacePackage\r
29from Library.Parsing import GetWorkspaceModule\r
5692fa88 30from Library.Parsing import GetPkgInfoFromDec\r
421ccda3
HC
31from Library.Misc import GetRelativePath\r
32from Library import GlobalData\r
4234283c
LG
33from Logger.ToolError import FatalError\r
34from Logger.ToolError import EDK1_INF_ERROR\r
35from Logger.ToolError import UNKNOWN_ERROR\r
36(DEPEX_CHECK_SUCCESS, DEPEX_CHECK_MODULE_NOT_FOUND, \\r
37DEPEX_CHECK_PACKAGE_NOT_FOUND, DEPEX_CHECK_DP_NOT_FOUND) = (0, 1, 2, 3)\r
38\r
39\r
421ccda3 40## DependencyRules\r
4234283c 41#\r
421ccda3 42# This class represents the dependency rule check mechanism\r
4234283c
LG
43# \r
44# @param object: Inherited from object class\r
45#\r
46class DependencyRules(object):\r
56636814 47 def __init__(self, Datab, ToBeInstalledPkgList=None):\r
4234283c
LG
48 self.IpiDb = Datab\r
49 self.WsPkgList = GetWorkspacePackage()\r
50 self.WsModuleList = GetWorkspaceModule()\r
56636814
HC
51\r
52 self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
53\r
54 # Add package info from the DIST to be installed.\r
55 self.PkgsToBeDepend.extend(self.GenToBeInstalledPkgList(ToBeInstalledPkgList))\r
421ccda3 56 \r
56636814 57 def GenToBeInstalledPkgList(self, ToBeInstalledPkgList):\r
f71b1630
HC
58 if not ToBeInstalledPkgList:\r
59 return []\r
56636814
HC
60 RtnList = []\r
61 for Dist in ToBeInstalledPkgList:\r
62 for Package in Dist.PackageSurfaceArea:\r
63 RtnList.append((Package[0], Package[1]))\r
64\r
65 return RtnList\r
66\r
421ccda3 67 ## Check whether a module exists by checking the Guid+Version+Name+Path combination\r
4234283c
LG
68 #\r
69 # @param Guid: Guid of a module\r
70 # @param Version: Version of a module\r
421ccda3
HC
71 # @param Name: Name of a module\r
72 # @param Path: Path of a module\r
73 # @return: True if module existed, else False\r
4234283c 74 #\r
421ccda3 75 def CheckModuleExists(self, Guid, Version, Name, Path):\r
4234283c 76 Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST)\r
d0acc87a
LG
77 ModuleList = self.IpiDb.GetModInPackage(Guid, Version, Name, Path)\r
78 ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version, Name, Path))\r
4234283c
LG
79 Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST_FINISH)\r
80 if len(ModuleList) > 0:\r
81 return True\r
82 else:\r
83 return False\r
84 \r
421ccda3 85 ## Check whether a module depex satisfied.\r
4234283c
LG
86 #\r
87 # @param ModuleObj: A module object\r
421ccda3
HC
88 # @param DpObj: A distribution object\r
89 # @return: True if module depex satisfied\r
90 # False else\r
4234283c 91 #\r
421ccda3 92 def CheckModuleDepexSatisfied(self, ModuleObj, DpObj=None):\r
4234283c
LG
93 Logger.Verbose(ST.MSG_CHECK_MODULE_DEPEX_START)\r
94 Result = True\r
95 Dep = None\r
96 if ModuleObj.GetPackageDependencyList():\r
97 Dep = ModuleObj.GetPackageDependencyList()[0]\r
98 for Dep in ModuleObj.GetPackageDependencyList():\r
99 #\r
100 # first check whether the dependency satisfied by current workspace\r
101 #\r
102 Exist = self.CheckPackageExists(Dep.GetGuid(), Dep.GetVersion())\r
103 #\r
104 # check whether satisfied by current distribution \r
105 #\r
106 if not Exist:\r
4231a819 107 if DpObj is None:\r
4234283c
LG
108 Result = False\r
109 break\r
110 for GuidVerPair in DpObj.PackageSurfaceArea.keys():\r
111 if Dep.GetGuid() == GuidVerPair[0]:\r
4231a819 112 if Dep.GetVersion() is None or \\r
4234283c
LG
113 len(Dep.GetVersion()) == 0:\r
114 Result = True\r
115 break\r
116 if Dep.GetVersion() == GuidVerPair[1]:\r
117 Result = True\r
118 break\r
119 else:\r
120 Result = False\r
121 break\r
122 \r
123 if not Result:\r
124 Logger.Error("CheckModuleDepex", UNKNOWN_ERROR, \\r
125 ST.ERR_DEPENDENCY_NOT_MATCH % (ModuleObj.GetName(), \\r
126 Dep.GetPackageFilePath(), \\r
127 Dep.GetGuid(), \\r
128 Dep.GetVersion()))\r
129 return Result\r
130 \r
421ccda3 131 ## Check whether a package exists in a package list specified by PkgsToBeDepend.\r
4234283c
LG
132 #\r
133 # @param Guid: Guid of a package\r
134 # @param Version: Version of a package\r
421ccda3
HC
135 # @return: True if package exist\r
136 # False else\r
4234283c
LG
137 #\r
138 def CheckPackageExists(self, Guid, Version):\r
139 Logger.Verbose(ST.MSG_CHECK_PACKAGE_START)\r
421ccda3
HC
140 Found = False\r
141 for (PkgGuid, PkgVer) in self.PkgsToBeDepend:\r
4234283c
LG
142 if (PkgGuid == Guid):\r
143 #\r
144 # if version is not empty and not equal, then not match\r
145 #\r
146 if Version and (PkgVer != Version):\r
421ccda3
HC
147 Found = False\r
148 break\r
4234283c 149 else:\r
421ccda3
HC
150 Found = True\r
151 break\r
4234283c 152 else:\r
421ccda3
HC
153 Found = False\r
154\r
4234283c 155 Logger.Verbose(ST.MSG_CHECK_PACKAGE_FINISH)\r
421ccda3 156 return Found\r
4234283c 157 \r
421ccda3 158 ## Check whether a package depex satisfied.\r
4234283c
LG
159 #\r
160 # @param PkgObj: A package object\r
421ccda3
HC
161 # @param DpObj: A distribution object\r
162 # @return: True if package depex satisified\r
163 # False else\r
4234283c 164 #\r
421ccda3 165 def CheckPackageDepexSatisfied(self, PkgObj, DpObj=None):\r
4234283c
LG
166 ModuleDict = PkgObj.GetModuleDict()\r
167 for ModKey in ModuleDict.keys():\r
168 ModObj = ModuleDict[ModKey]\r
421ccda3 169 if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
4234283c
LG
170 continue\r
171 else:\r
172 return False\r
173 return True\r
174 \r
421ccda3 175 ## Check whether a DP exists.\r
4234283c 176 #\r
421ccda3
HC
177 # @param Guid: Guid of a Distribution\r
178 # @param Version: Version of a Distribution\r
179 # @return: True if Distribution exist\r
180 # False else\r
181 def CheckDpExists(self, Guid, Version):\r
4234283c
LG
182 Logger.Verbose(ST.MSG_CHECK_DP_START)\r
183 DpList = self.IpiDb.GetDp(Guid, Version)\r
184 if len(DpList) > 0:\r
421ccda3 185 Found = True\r
4234283c 186 else:\r
421ccda3
HC
187 Found = False\r
188\r
189 Logger.Verbose(ST.MSG_CHECK_DP_FINISH)\r
190 return Found\r
191\r
192 ## Check whether a DP depex satisfied by current workspace for Install\r
193 #\r
194 # @param DpObj: A distribution object\r
195 # @return: True if distribution depex satisfied\r
196 # False else\r
197 #\r
198 def CheckInstallDpDepexSatisfied(self, DpObj):\r
421ccda3
HC
199 return self.CheckDpDepexSatisfied(DpObj)\r
200\r
6cf99034
HC
201 # # Check whether multiple DP depex satisfied by current workspace for Install\r
202 #\r
203 # @param DpObjList: A distribution object list\r
204 # @return: True if distribution depex satisfied\r
205 # False else\r
206 #\r
207 def CheckTestInstallPdDepexSatisfied(self, DpObjList):\r
6cf99034
HC
208 for DpObj in DpObjList:\r
209 if self.CheckDpDepexSatisfied(DpObj):\r
210 for PkgKey in DpObj.PackageSurfaceArea.keys():\r
211 PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
212 self.PkgsToBeDepend.append((PkgObj.Guid, PkgObj.Version))\r
213 else:\r
214 return False, DpObj\r
215\r
216 return True, DpObj\r
217\r
218\r
421ccda3
HC
219 ## Check whether a DP depex satisfied by current workspace \r
220 # (excluding the original distribution's packages to be replaced) for Replace\r
221 #\r
222 # @param DpObj: A distribution object\r
223 # @param OrigDpGuid: The original distribution's Guid\r
224 # @param OrigDpVersion: The original distribution's Version\r
225 #\r
226 def ReplaceCheckNewDpDepex(self, DpObj, OrigDpGuid, OrigDpVersion):\r
227 self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
228 OrigDpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion)\r
229 for OrigPkgInfo in OrigDpPackageList:\r
230 Guid, Version = OrigPkgInfo[0], OrigPkgInfo[1]\r
231 if (Guid, Version) in self.PkgsToBeDepend:\r
232 self.PkgsToBeDepend.remove((Guid, Version))\r
233 return self.CheckDpDepexSatisfied(DpObj)\r
234\r
4234283c
LG
235 ## Check whether a DP depex satisfied by current workspace.\r
236 #\r
421ccda3 237 # @param DpObj: A distribution object\r
4234283c 238 #\r
421ccda3 239 def CheckDpDepexSatisfied(self, DpObj):\r
4234283c
LG
240 for PkgKey in DpObj.PackageSurfaceArea.keys():\r
241 PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
421ccda3 242 if self.CheckPackageDepexSatisfied(PkgObj, DpObj):\r
4234283c
LG
243 continue\r
244 else:\r
245 return False\r
246 \r
247 for ModKey in DpObj.ModuleSurfaceArea.keys():\r
248 ModObj = DpObj.ModuleSurfaceArea[ModKey]\r
421ccda3 249 if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
4234283c
LG
250 continue\r
251 else:\r
252 return False\r
253 \r
254 return True\r
255 \r
421ccda3 256 ## Check whether a DP could be removed from current workspace. \r
4234283c
LG
257 #\r
258 # @param DpGuid: File's guid\r
259 # @param DpVersion: File's version\r
421ccda3
HC
260 # @retval Removable: True if distribution could be removed, False Else\r
261 # @retval DependModuleList: the list of modules that make distribution can not be removed\r
262 #\r
263 def CheckDpDepexForRemove(self, DpGuid, DpVersion):\r
4234283c
LG
264 Removable = True\r
265 DependModuleList = []\r
266 WsModuleList = self.WsModuleList\r
267 #\r
268 # remove modules that included in current DP\r
269 # List of item (FilePath)\r
270 DpModuleList = self.IpiDb.GetDpModuleList(DpGuid, DpVersion) \r
271 for Module in DpModuleList:\r
272 if Module in WsModuleList:\r
273 WsModuleList.remove(Module)\r
274 else:\r
275 Logger.Warn("UPT\n",\r
276 ST.ERR_MODULE_NOT_INSTALLED % Module)\r
277 #\r
278 # get packages in current Dp and find the install path\r
279 # List of item (PkgGuid, PkgVersion, InstallPath)\r
280 DpPackageList = self.IpiDb.GetPackageListFromDp(DpGuid, DpVersion) \r
281 DpPackagePathList = []\r
421ccda3 282 WorkSP = GlobalData.gWORKSPACE\r
4234283c
LG
283 for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
284 if PkgName:\r
285 pass\r
286 DecPath = dirname(DecFile)\r
287 if DecPath.find(WorkSP) > -1:\r
421ccda3
HC
288 InstallPath = GetRelativePath(DecPath,WorkSP)\r
289 DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
4234283c
LG
290 else:\r
291 InstallPath = DecPath\r
292 DecFileRelaPath = DecFile\r
293 \r
294 if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
295 DpPackagePathList.append(DecFileRelaPath)\r
296 DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
297 \r
298 #\r
299 # the left items in DpPackageList are the packages that installed but not found anymore\r
300 #\r
301 for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
302 Logger.Warn("UPT",\r
303 ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
304 \r
305 #\r
306 # check modules to see if has dependency on package of current DP\r
307 #\r
308 for Module in WsModuleList:\r
421ccda3 309 if (not VerifyRemoveModuleDep(Module, DpPackagePathList)):\r
4234283c
LG
310 Removable = False\r
311 DependModuleList.append(Module)\r
312 return (Removable, DependModuleList)\r
313\r
314\r
421ccda3
HC
315 ## Check whether a DP could be replaced by a distribution containing NewDpPkgList\r
316 # from current workspace.\r
317 #\r
318 # @param OrigDpGuid: original Dp's Guid\r
319 # @param OrigDpVersion: original Dp's version\r
320 # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp\r
321 # @retval Replaceable: True if distribution could be replaced, False Else\r
322 # @retval DependModuleList: the list of modules that make distribution can not be replaced\r
323 # \r
324 def CheckDpDepexForReplace(self, OrigDpGuid, OrigDpVersion, NewDpPkgList):\r
325 Replaceable = True\r
326 DependModuleList = []\r
327 WsModuleList = self.WsModuleList\r
328 #\r
329 # remove modules that included in current DP\r
330 # List of item (FilePath)\r
331 DpModuleList = self.IpiDb.GetDpModuleList(OrigDpGuid, OrigDpVersion) \r
332 for Module in DpModuleList:\r
333 if Module in WsModuleList:\r
334 WsModuleList.remove(Module)\r
335 else:\r
336 Logger.Warn("UPT\n",\r
337 ST.ERR_MODULE_NOT_INSTALLED % Module)\r
338 \r
339 OtherPkgList = NewDpPkgList\r
340 #\r
341 # get packages in current Dp and find the install path\r
342 # List of item (PkgGuid, PkgVersion, InstallPath)\r
343 DpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion) \r
344 DpPackagePathList = []\r
345 WorkSP = GlobalData.gWORKSPACE\r
346 for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
347 if PkgName:\r
348 pass\r
349 DecPath = dirname(DecFile)\r
350 if DecPath.find(WorkSP) > -1:\r
351 InstallPath = GetRelativePath(DecPath,WorkSP)\r
352 DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
353 else:\r
354 InstallPath = DecPath\r
355 DecFileRelaPath = DecFile\r
356 \r
357 if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
358 DpPackagePathList.append(DecFileRelaPath)\r
359 DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
360 else:\r
361 OtherPkgList.append((PkgGuid, PkgVersion))\r
362\r
363 #\r
364 # the left items in DpPackageList are the packages that installed but not found anymore\r
365 #\r
366 for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
367 Logger.Warn("UPT",\r
368 ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
369 \r
370 #\r
371 # check modules to see if it can be satisfied by package not belong to removed DP\r
372 #\r
373 for Module in WsModuleList:\r
374 if (not VerifyReplaceModuleDep(Module, DpPackagePathList, OtherPkgList)):\r
375 Replaceable = False\r
376 DependModuleList.append(Module)\r
377 return (Replaceable, DependModuleList)\r
378\r
379 \r
4234283c
LG
380## check whether module depends on packages in DpPackagePathList, return True \r
381# if found, False else\r
382#\r
383# @param Path: a module path\r
384# @param DpPackagePathList: a list of Package Paths\r
421ccda3
HC
385# @retval: False: module depends on package in DpPackagePathList\r
386# True: module doesn't depend on package in DpPackagePathList\r
4234283c 387#\r
421ccda3 388def VerifyRemoveModuleDep(Path, DpPackagePathList):\r
4234283c 389 try:\r
5692fa88
HC
390 for Item in GetPackagePath(Path):\r
391 if Item in DpPackagePathList:\r
392 DecPath = os.path.normpath(os.path.join(GlobalData.gWORKSPACE, Item))\r
393 Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, DecPath))\r
421ccda3 394 return False\r
4234283c 395 else:\r
421ccda3 396 return True\r
5b0671c1 397 except FatalError as ErrCode:\r
4234283c
LG
398 if ErrCode.message == EDK1_INF_ERROR:\r
399 Logger.Warn("UPT",\r
400 ST.WRN_EDK1_INF_FOUND%Path)\r
421ccda3 401 return True\r
4234283c 402 else:\r
421ccda3
HC
403 return True\r
404\r
5692fa88
HC
405# # GetPackagePath\r
406#\r
407# Get Dependency package path from an Inf file path\r
408#\r
409def GetPackagePath(InfPath):\r
410 PackagePath = []\r
411 if os.path.exists(InfPath):\r
412 FindSection = False\r
413 for Line in open(InfPath).readlines():\r
414 Line = Line.strip()\r
415 if not Line:\r
416 continue\r
417 if Line.startswith('#'):\r
418 continue\r
419 if Line.startswith('[Packages') and Line.endswith(']'):\r
420 FindSection = True\r
421 continue\r
422 if Line.startswith('[') and Line.endswith(']') and FindSection:\r
423 break\r
424 if FindSection:\r
425 PackagePath.append(os.path.normpath(Line))\r
426\r
427 return PackagePath\r
428\r
421ccda3
HC
429## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList\r
430#\r
431# @param Path: a module path\r
432# @param DpPackagePathList: a list of Package Paths\r
433# @param OtherPkgList: a list of Package Information (Guid, Version)\r
434# @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList\r
435# True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList \r
436# but can be satisfied by OtherPkgList\r
437#\r
438def VerifyReplaceModuleDep(Path, DpPackagePathList, OtherPkgList):\r
421ccda3 439 try:\r
5692fa88
HC
440 for Item in GetPackagePath(Path):\r
441 if Item in DpPackagePathList:\r
442 DecPath = os.path.normpath(os.path.join(GlobalData.gWORKSPACE, Item))\r
443 Name, Guid, Version = GetPkgInfoFromDec(DecPath)\r
421ccda3 444 if (Guid, Version) not in OtherPkgList:\r
5692fa88 445 Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, DecPath))\r
421ccda3
HC
446 return False\r
447 else:\r
448 return True\r
5b0671c1 449 except FatalError as ErrCode:\r
421ccda3
HC
450 if ErrCode.message == EDK1_INF_ERROR:\r
451 Logger.Warn("UPT",\r
452 ST.WRN_EDK1_INF_FOUND%Path)\r
453 return True\r
454 else:\r
455 return True\r