]>
Commit | Line | Data |
---|---|---|
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 | |
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 | |
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 |
356 | def 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 | |
385 | def 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 |