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