## @file\r
# This file is for installed package information database operations\r
#\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>\r
#\r
# This program and the accompanying materials are licensed and made available \r
# under the terms and conditions of the BSD License which accompanies this \r
##\r
# Import Modules\r
#\r
-from os import getenv\r
-from os import environ\r
from os.path import dirname\r
+import os\r
\r
import Logger.Log as Logger\r
from Logger import StringTable as ST\r
from Library.Parsing import GetWorkspacePackage\r
from Library.Parsing import GetWorkspaceModule\r
-from PomAdapter.InfPomAlignment import InfPomAlignment\r
+from Library.Parsing import GetPkgInfoFromDec\r
+from Library.Misc import GetRelativePath\r
+from Library import GlobalData\r
from Logger.ToolError import FatalError\r
from Logger.ToolError import EDK1_INF_ERROR\r
from Logger.ToolError import UNKNOWN_ERROR\r
DEPEX_CHECK_PACKAGE_NOT_FOUND, DEPEX_CHECK_DP_NOT_FOUND) = (0, 1, 2, 3)\r
\r
\r
-## IpiDb\r
+## DependencyRules\r
#\r
-# This class represents the installed package information database\r
-# Add/Remove/Get installed distribution package information here.\r
-# \r
+# This class represents the dependency rule check mechanism\r
# \r
# @param object: Inherited from object class\r
#\r
class DependencyRules(object):\r
- def __init__(self, Datab):\r
+ def __init__(self, Datab, ToBeInstalledPkgList=None):\r
self.IpiDb = Datab\r
self.WsPkgList = GetWorkspacePackage()\r
self.WsModuleList = GetWorkspaceModule()\r
\r
- ## Check whether a module exists in current workspace.\r
+ self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
+\r
+ # Add package info from the DIST to be installed.\r
+ self.PkgsToBeDepend.extend(self.GenToBeInstalledPkgList(ToBeInstalledPkgList))\r
+ \r
+ def GenToBeInstalledPkgList(self, ToBeInstalledPkgList):\r
+ if not ToBeInstalledPkgList:\r
+ return []\r
+ RtnList = []\r
+ for Dist in ToBeInstalledPkgList:\r
+ for Package in Dist.PackageSurfaceArea:\r
+ RtnList.append((Package[0], Package[1]))\r
+\r
+ return RtnList\r
+\r
+ ## Check whether a module exists by checking the Guid+Version+Name+Path combination\r
#\r
# @param Guid: Guid of a module\r
# @param Version: Version of a module\r
+ # @param Name: Name of a module\r
+ # @param Path: Path of a module\r
+ # @return: True if module existed, else False\r
#\r
- def CheckModuleExists(self, Guid, Version, ReturnCode=DEPEX_CHECK_SUCCESS):\r
- if ReturnCode:\r
- pass\r
+ def CheckModuleExists(self, Guid, Version, Name, Path):\r
Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST)\r
- ModuleList = self.IpiDb.GetModInPackage(Guid, Version)\r
- ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version))\r
+ ModuleList = self.IpiDb.GetModInPackage(Guid, Version, Name, Path)\r
+ ModuleList.extend(self.IpiDb.GetStandaloneModule(Guid, Version, Name, Path))\r
Logger.Verbose(ST.MSG_CHECK_MODULE_EXIST_FINISH)\r
if len(ModuleList) > 0:\r
return True\r
else:\r
return False\r
\r
- ## Check whether a module depex satisfied by current workspace or dist.\r
+ ## Check whether a module depex satisfied.\r
#\r
# @param ModuleObj: A module object\r
- # @param DpObj: A depex object\r
+ # @param DpObj: A distribution object\r
+ # @return: True if module depex satisfied\r
+ # False else\r
#\r
- def CheckModuleDepexSatisfied(self, ModuleObj, DpObj=None, \\r
- ReturnCode=DEPEX_CHECK_SUCCESS):\r
- if ReturnCode:\r
- pass\r
+ def CheckModuleDepexSatisfied(self, ModuleObj, DpObj=None):\r
Logger.Verbose(ST.MSG_CHECK_MODULE_DEPEX_START)\r
Result = True\r
Dep = None\r
# check whether satisfied by current distribution \r
#\r
if not Exist:\r
- if DpObj == None:\r
+ if DpObj is None:\r
Result = False\r
break\r
for GuidVerPair in DpObj.PackageSurfaceArea.keys():\r
if Dep.GetGuid() == GuidVerPair[0]:\r
- if Dep.GetVersion() == None or \\r
+ if Dep.GetVersion() is None or \\r
len(Dep.GetVersion()) == 0:\r
Result = True\r
break\r
Dep.GetVersion()))\r
return Result\r
\r
- ## Check whether a package exists in current workspace.\r
+ ## Check whether a package exists in a package list specified by PkgsToBeDepend.\r
#\r
# @param Guid: Guid of a package\r
# @param Version: Version of a package\r
+ # @return: True if package exist\r
+ # False else\r
#\r
def CheckPackageExists(self, Guid, Version):\r
Logger.Verbose(ST.MSG_CHECK_PACKAGE_START)\r
- for (PkgName, PkgGuid, PkgVer, PkgPath) in self.WsPkgList:\r
- if PkgName or PkgPath:\r
- pass\r
+ Found = False\r
+ for (PkgGuid, PkgVer) in self.PkgsToBeDepend:\r
if (PkgGuid == Guid):\r
#\r
# if version is not empty and not equal, then not match\r
#\r
if Version and (PkgVer != Version):\r
- return False\r
+ Found = False\r
+ break\r
else:\r
- return True\r
+ Found = True\r
+ break\r
else:\r
- return False\r
- \r
+ Found = False\r
+\r
Logger.Verbose(ST.MSG_CHECK_PACKAGE_FINISH)\r
+ return Found\r
\r
- ## Check whether a package depex satisfied by current workspace.\r
+ ## Check whether a package depex satisfied.\r
#\r
# @param PkgObj: A package object\r
- # @param DpObj: A package depex object\r
+ # @param DpObj: A distribution object\r
+ # @return: True if package depex satisified\r
+ # False else\r
#\r
- def CheckPackageDepexSatisfied(self, PkgObj, DpObj=None, \\r
- ReturnCode=DEPEX_CHECK_SUCCESS):\r
- \r
+ def CheckPackageDepexSatisfied(self, PkgObj, DpObj=None):\r
ModuleDict = PkgObj.GetModuleDict()\r
for ModKey in ModuleDict.keys():\r
ModObj = ModuleDict[ModKey]\r
- if self.CheckModuleDepexSatisfied(ModObj, DpObj, ReturnCode):\r
+ if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
continue\r
else:\r
return False\r
return True\r
\r
- ## Check whether a DP exists in current workspace.\r
- #\r
- # @param Guid: Guid of a module\r
- # @param Version: Version of a module\r
+ ## Check whether a DP exists.\r
#\r
- def CheckDpExists(self, Guid, Version, ReturnCode=DEPEX_CHECK_SUCCESS):\r
- if ReturnCode:\r
- pass\r
+ # @param Guid: Guid of a Distribution\r
+ # @param Version: Version of a Distribution\r
+ # @return: True if Distribution exist\r
+ # False else\r
+ def CheckDpExists(self, Guid, Version):\r
Logger.Verbose(ST.MSG_CHECK_DP_START)\r
DpList = self.IpiDb.GetDp(Guid, Version)\r
if len(DpList) > 0:\r
- return True\r
+ Found = True\r
else:\r
- return False\r
- \r
- Logger.Verbose(ST.MSG_CHECK_DP_FINISH) \r
- \r
+ Found = False\r
+\r
+ Logger.Verbose(ST.MSG_CHECK_DP_FINISH)\r
+ return Found\r
+\r
+ ## Check whether a DP depex satisfied by current workspace for Install\r
+ #\r
+ # @param DpObj: A distribution object\r
+ # @return: True if distribution depex satisfied\r
+ # False else\r
+ #\r
+ def CheckInstallDpDepexSatisfied(self, DpObj):\r
+ return self.CheckDpDepexSatisfied(DpObj)\r
+\r
+ # # Check whether multiple DP depex satisfied by current workspace for Install\r
+ #\r
+ # @param DpObjList: A distribution object list\r
+ # @return: True if distribution depex satisfied\r
+ # False else\r
+ #\r
+ def CheckTestInstallPdDepexSatisfied(self, DpObjList):\r
+ for DpObj in DpObjList:\r
+ if self.CheckDpDepexSatisfied(DpObj):\r
+ for PkgKey in DpObj.PackageSurfaceArea.keys():\r
+ PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
+ self.PkgsToBeDepend.append((PkgObj.Guid, PkgObj.Version))\r
+ else:\r
+ return False, DpObj\r
+\r
+ return True, DpObj\r
+\r
+\r
+ ## Check whether a DP depex satisfied by current workspace \r
+ # (excluding the original distribution's packages to be replaced) for Replace\r
+ #\r
+ # @param DpObj: A distribution object\r
+ # @param OrigDpGuid: The original distribution's Guid\r
+ # @param OrigDpVersion: The original distribution's Version\r
+ #\r
+ def ReplaceCheckNewDpDepex(self, DpObj, OrigDpGuid, OrigDpVersion):\r
+ self.PkgsToBeDepend = [(PkgInfo[1], PkgInfo[2]) for PkgInfo in self.WsPkgList]\r
+ OrigDpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion)\r
+ for OrigPkgInfo in OrigDpPackageList:\r
+ Guid, Version = OrigPkgInfo[0], OrigPkgInfo[1]\r
+ if (Guid, Version) in self.PkgsToBeDepend:\r
+ self.PkgsToBeDepend.remove((Guid, Version))\r
+ return self.CheckDpDepexSatisfied(DpObj)\r
+\r
## Check whether a DP depex satisfied by current workspace.\r
#\r
- # @param DpObj: Depex object\r
- # @param ReturnCode: ReturnCode\r
+ # @param DpObj: A distribution object\r
#\r
- def CheckDpDepexSatisfied(self, DpObj, ReturnCode=DEPEX_CHECK_SUCCESS):\r
- \r
+ def CheckDpDepexSatisfied(self, DpObj):\r
for PkgKey in DpObj.PackageSurfaceArea.keys():\r
PkgObj = DpObj.PackageSurfaceArea[PkgKey]\r
- if self.CheckPackageDepexSatisfied(PkgObj, DpObj, ReturnCode):\r
+ if self.CheckPackageDepexSatisfied(PkgObj, DpObj):\r
continue\r
else:\r
return False\r
\r
for ModKey in DpObj.ModuleSurfaceArea.keys():\r
ModObj = DpObj.ModuleSurfaceArea[ModKey]\r
- if self.CheckModuleDepexSatisfied(ModObj, DpObj, ReturnCode):\r
+ if self.CheckModuleDepexSatisfied(ModObj, DpObj):\r
continue\r
else:\r
return False\r
\r
return True\r
\r
- ## Check whether a DP depex satisfied by current workspace. Return False \r
- # if Can not remove (there is dependency), True else\r
+ ## Check whether a DP could be removed from current workspace. \r
#\r
# @param DpGuid: File's guid\r
# @param DpVersion: File's version\r
- # @param ReturnCode: ReturnCode\r
- # \r
- def CheckDpDepexForRemove(self, DpGuid, DpVersion, \\r
- ReturnCode=DEPEX_CHECK_SUCCESS):\r
- if ReturnCode:\r
- pass\r
+ # @retval Removable: True if distribution could be removed, False Else\r
+ # @retval DependModuleList: the list of modules that make distribution can not be removed\r
+ #\r
+ def CheckDpDepexForRemove(self, DpGuid, DpVersion):\r
Removable = True\r
DependModuleList = []\r
WsModuleList = self.WsModuleList\r
# List of item (PkgGuid, PkgVersion, InstallPath)\r
DpPackageList = self.IpiDb.GetPackageListFromDp(DpGuid, DpVersion) \r
DpPackagePathList = []\r
- WorkSP = environ["WORKSPACE"]\r
+ WorkSP = GlobalData.gWORKSPACE\r
for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
if PkgName:\r
pass\r
DecPath = dirname(DecFile)\r
if DecPath.find(WorkSP) > -1:\r
- InstallPath = DecPath[DecPath.find(WorkSP) + len(WorkSP) + 1:]\r
- DecFileRelaPath = \\r
- DecFile[DecFile.find(WorkSP) + len(WorkSP) + 1:]\r
+ InstallPath = GetRelativePath(DecPath,WorkSP)\r
+ DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
else:\r
InstallPath = DecPath\r
DecFileRelaPath = DecFile\r
# check modules to see if has dependency on package of current DP\r
#\r
for Module in WsModuleList:\r
- if (CheckModuleDependFromInf(Module, DpPackagePathList)):\r
+ if (not VerifyRemoveModuleDep(Module, DpPackagePathList)):\r
Removable = False\r
DependModuleList.append(Module)\r
return (Removable, DependModuleList)\r
\r
\r
+ ## Check whether a DP could be replaced by a distribution containing NewDpPkgList\r
+ # from current workspace.\r
+ #\r
+ # @param OrigDpGuid: original Dp's Guid\r
+ # @param OrigDpVersion: original Dp's version\r
+ # @param NewDpPkgList: a list of package information (Guid, Version) in new Dp\r
+ # @retval Replaceable: True if distribution could be replaced, False Else\r
+ # @retval DependModuleList: the list of modules that make distribution can not be replaced\r
+ # \r
+ def CheckDpDepexForReplace(self, OrigDpGuid, OrigDpVersion, NewDpPkgList):\r
+ Replaceable = True\r
+ DependModuleList = []\r
+ WsModuleList = self.WsModuleList\r
+ #\r
+ # remove modules that included in current DP\r
+ # List of item (FilePath)\r
+ DpModuleList = self.IpiDb.GetDpModuleList(OrigDpGuid, OrigDpVersion) \r
+ for Module in DpModuleList:\r
+ if Module in WsModuleList:\r
+ WsModuleList.remove(Module)\r
+ else:\r
+ Logger.Warn("UPT\n",\r
+ ST.ERR_MODULE_NOT_INSTALLED % Module)\r
+ \r
+ OtherPkgList = NewDpPkgList\r
+ #\r
+ # get packages in current Dp and find the install path\r
+ # List of item (PkgGuid, PkgVersion, InstallPath)\r
+ DpPackageList = self.IpiDb.GetPackageListFromDp(OrigDpGuid, OrigDpVersion) \r
+ DpPackagePathList = []\r
+ WorkSP = GlobalData.gWORKSPACE\r
+ for (PkgName, PkgGuid, PkgVersion, DecFile) in self.WsPkgList:\r
+ if PkgName:\r
+ pass\r
+ DecPath = dirname(DecFile)\r
+ if DecPath.find(WorkSP) > -1:\r
+ InstallPath = GetRelativePath(DecPath,WorkSP)\r
+ DecFileRelaPath = GetRelativePath(DecFile,WorkSP)\r
+ else:\r
+ InstallPath = DecPath\r
+ DecFileRelaPath = DecFile\r
+ \r
+ if (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
+ DpPackagePathList.append(DecFileRelaPath)\r
+ DpPackageList.remove((PkgGuid, PkgVersion, InstallPath))\r
+ else:\r
+ OtherPkgList.append((PkgGuid, PkgVersion))\r
+\r
+ #\r
+ # the left items in DpPackageList are the packages that installed but not found anymore\r
+ #\r
+ for (PkgGuid, PkgVersion, InstallPath) in DpPackageList:\r
+ Logger.Warn("UPT",\r
+ ST.WARN_INSTALLED_PACKAGE_NOT_FOUND%(PkgGuid, PkgVersion, InstallPath))\r
+ \r
+ #\r
+ # check modules to see if it can be satisfied by package not belong to removed DP\r
+ #\r
+ for Module in WsModuleList:\r
+ if (not VerifyReplaceModuleDep(Module, DpPackagePathList, OtherPkgList)):\r
+ Replaceable = False\r
+ DependModuleList.append(Module)\r
+ return (Replaceable, DependModuleList)\r
+\r
+ \r
## check whether module depends on packages in DpPackagePathList, return True \r
# if found, False else\r
#\r
# @param Path: a module path\r
# @param DpPackagePathList: a list of Package Paths\r
+# @retval: False: module depends on package in DpPackagePathList\r
+# True: module doesn't depend on package in DpPackagePathList\r
#\r
-def CheckModuleDependFromInf(Path, DpPackagePathList):\r
- \r
- # \r
- # use InfParser to parse inf, then get the information for now,\r
- # later on, may consider only parse to get the package dependency info \r
- # (Need to take care how to deal wit Macros)\r
- #\r
- WorkSP = getenv('WORKSPACE')\r
- \r
+def VerifyRemoveModuleDep(Path, DpPackagePathList):\r
try:\r
- PomAli = InfPomAlignment(Path, WorkSP, Skip=True)\r
-\r
- for Item in PomAli.GetPackageDependencyList():\r
- if Item.GetPackageFilePath() in DpPackagePathList:\r
- Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, Item.GetPackageFilePath()))\r
- return True\r
+ for Item in GetPackagePath(Path):\r
+ if Item in DpPackagePathList:\r
+ DecPath = os.path.normpath(os.path.join(GlobalData.gWORKSPACE, Item))\r
+ Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, DecPath))\r
+ return False\r
else:\r
- return False\r
- except FatalError, ErrCode:\r
+ return True\r
+ except FatalError as ErrCode:\r
if ErrCode.message == EDK1_INF_ERROR:\r
Logger.Warn("UPT",\r
ST.WRN_EDK1_INF_FOUND%Path)\r
- return False\r
+ return True\r
else:\r
- return False\r
- \r
+ return True\r
+\r
+# # GetPackagePath\r
+#\r
+# Get Dependency package path from an Inf file path\r
+#\r
+def GetPackagePath(InfPath):\r
+ PackagePath = []\r
+ if os.path.exists(InfPath):\r
+ FindSection = False\r
+ for Line in open(InfPath).readlines():\r
+ Line = Line.strip()\r
+ if not Line:\r
+ continue\r
+ if Line.startswith('#'):\r
+ continue\r
+ if Line.startswith('[Packages') and Line.endswith(']'):\r
+ FindSection = True\r
+ continue\r
+ if Line.startswith('[') and Line.endswith(']') and FindSection:\r
+ break\r
+ if FindSection:\r
+ PackagePath.append(os.path.normpath(Line))\r
\r
+ return PackagePath\r
\r
+## check whether module depends on packages in DpPackagePathList and can not be satisfied by OtherPkgList\r
+#\r
+# @param Path: a module path\r
+# @param DpPackagePathList: a list of Package Paths\r
+# @param OtherPkgList: a list of Package Information (Guid, Version)\r
+# @retval: False: module depends on package in DpPackagePathList and can not be satisfied by OtherPkgList\r
+# True: either module doesn't depend on DpPackagePathList or module depends on DpPackagePathList \r
+# but can be satisfied by OtherPkgList\r
+#\r
+def VerifyReplaceModuleDep(Path, DpPackagePathList, OtherPkgList):\r
+ try:\r
+ for Item in GetPackagePath(Path):\r
+ if Item in DpPackagePathList:\r
+ DecPath = os.path.normpath(os.path.join(GlobalData.gWORKSPACE, Item))\r
+ Name, Guid, Version = GetPkgInfoFromDec(DecPath)\r
+ if (Guid, Version) not in OtherPkgList:\r
+ Logger.Info(ST.MSG_MODULE_DEPEND_ON % (Path, DecPath))\r
+ return False\r
+ else:\r
+ return True\r
+ except FatalError as ErrCode:\r
+ if ErrCode.message == EDK1_INF_ERROR:\r
+ Logger.Warn("UPT",\r
+ ST.WRN_EDK1_INF_FOUND%Path)\r
+ return True\r
+ else:\r
+ return True\r