]>
Commit | Line | Data |
---|---|---|
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 | |
17 | Dependency\r | |
18 | '''\r | |
19 | \r | |
20 | ##\r | |
21 | # Import Modules\r | |
22 | #\r | |
4234283c LG |
23 | from os.path import dirname\r |
24 | \r | |
25 | import Logger.Log as Logger\r | |
26 | from Logger import StringTable as ST\r | |
27 | from Library.Parsing import GetWorkspacePackage\r | |
28 | from Library.Parsing import GetWorkspaceModule\r | |
421ccda3 HC |
29 | from Library.Misc import GetRelativePath\r |
30 | from Library import GlobalData\r | |
4234283c LG |
31 | from PomAdapter.InfPomAlignment import InfPomAlignment\r |
32 | from Logger.ToolError import FatalError\r | |
33 | from Logger.ToolError import EDK1_INF_ERROR\r | |
34 | from Logger.ToolError import UNKNOWN_ERROR\r | |
35 | (DEPEX_CHECK_SUCCESS, DEPEX_CHECK_MODULE_NOT_FOUND, \\r | |
36 | DEPEX_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 | |
45 | class 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 |
375 | def 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 | |
404 | def 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 |