support/package-builder/SpecData.py
2820c61a
 import os
87815216
 import queue
45c9260c
 import json
 import operator
87815216
 from distutils.version import StrictVersion
 from Logger import Logger
45c9260c
 from constants import constants
f93ef2b0
 from StringUtils import StringUtils
 from distutils.version import LooseVersion
4ed339b4
 from SpecParser import SpecParser
accc8120
 
 
4ed339b4
 class SpecData(object):
 
a007b861
     def __init__(self, arch, logPath, specFilesPath):
         self.arch = arch
4ed339b4
         self.logger = Logger.getLogger("SpecData", logPath, constants.logLevel)
 
         # map default package name to list of SpecObjects. Usually it is just
         # a list with only one element. But, for multiversion spec file this
         # list has as many elements as many versions of given package name
         # are available
5d822c2d
         self.mapSpecObjects = {}
4ed339b4
 
         # map subpackage names to default package name
87815216
         self.mapPackageToSpec = {}
4ed339b4
 
         # map spec file name to SpecObject
cfd85ba2
         self.mapSpecFileNameToSpecObj = {}
5062126c
 
4ed339b4
         self._readSpecs(specFilesPath)
 
ed27cf29
 
4ed339b4
     # Read all .spec files from the given folder including subfolders,
     # creates corresponding SpecObjects and put them in internal mappings.
     def _readSpecs(self, specFilesPath):
         for specFile in self._getListSpecFiles(specFilesPath):
a007b861
             spec = SpecParser(specFile, self.arch)
4ed339b4
 
             # skip the specfile if buildarch differs
             buildarch = spec.packages.get('default').buildarch
             if (buildarch != "noarch" and
a007b861
                     buildarch != self.arch):
ed27cf29
                 self.logger.info("skipping spec file: "+str(specFile))
                 continue
 
4ed339b4
             specObj = spec.createSpecObject()
 
             name = specObj.name
2820c61a
             for specPkg in specObj.listPackages:
4ed339b4
                 self.mapPackageToSpec[specPkg] = name
 
             if name in self.mapSpecObjects:
                 self.mapSpecObjects[name].append(specObj)
5d822c2d
             else:
4ed339b4
                 self.mapSpecObjects[name]=[specObj]
 
cfd85ba2
             self.mapSpecFileNameToSpecObj[os.path.basename(specFile)]=specObj
ed27cf29
 
4ed339b4
 
         # Sort the multiversion list to make getHighestVersion happy
5d822c2d
         for key, value in self.mapSpecObjects.items():
             if len(value) > 1:
                 self.mapSpecObjects[key] = sorted(value,
                                                   key=lambda x : self.compareVersions(x),
                                                   reverse=True)
5062126c
 
4ed339b4
     def _getListSpecFiles(self, path):
         listSpecFiles = []
2820c61a
         for dirEntry in os.listdir(path):
             dirEntryPath = os.path.join(path, dirEntry)
87815216
             if (os.path.isfile(dirEntryPath) and
ed27cf29
                     dirEntryPath.endswith(".spec")):
2820c61a
                 listSpecFiles.append(dirEntryPath)
             elif os.path.isdir(dirEntryPath):
4ed339b4
                 listSpecFiles.extend(self._getListSpecFiles(dirEntryPath))
         return listSpecFiles
5062126c
 
f93ef2b0
     def _getProperVersion(self,depPkg):
         if (depPkg.compare == ""):
             return self.getHighestVersion(depPkg.package)
4ed339b4
         specObjs=self.getSpecObjects(depPkg.package)
cfd85ba2
         try:
             for obj in specObjs:
f93ef2b0
                 verrel=obj.version+"-"+obj.release
                 if depPkg.compare == ">=":
cfd85ba2
                     if LooseVersion(verrel) >= LooseVersion(depPkg.version):
                         return obj.version
f93ef2b0
                 elif depPkg.compare == "<=":
cfd85ba2
                     if LooseVersion(verrel) <= LooseVersion(depPkg.version):
                         return obj.version
f93ef2b0
                 elif depPkg.compare == "=":
cfd85ba2
                     if LooseVersion(verrel) == LooseVersion(depPkg.version):
                         return obj.version
                     if LooseVersion(obj.version) == LooseVersion(depPkg.version):
                         return obj.version
f93ef2b0
                 elif depPkg.compare == "<":
cfd85ba2
                     if LooseVersion(verrel) < LooseVersion(depPkg.version):
                         return obj.version
f93ef2b0
                 elif depPkg.compare == ">":
cfd85ba2
                     if LooseVersion(verrel) > LooseVersion(depPkg.version):
                         return obj.version
         except Exception as e:
f8f09a53
             self.logger.error("Exception happened while searching for: " + \
                               depPkg.package + depPkg.compare + depPkg.version)
cfd85ba2
             raise e
f93ef2b0
 
         # about to throw exception
         availableVersions=""
         for obj in specObjs:
             availableVersions+=" "+obj.name+"-"+obj.version+"-"+obj.release
f8f09a53
         raise Exception("Could not find package: " + depPkg.package + \
                          depPkg.compare + depPkg.version + \
                          " available specs:" + availableVersions)
f93ef2b0
 
     def _getSpecObjField(self, package, version, field):
4ed339b4
         for specObj in self.getSpecObjects(package):
f93ef2b0
             if specObj.version == version:
                 return field(specObj)
f8f09a53
         self.logger.error("Could not find " + package +
f93ef2b0
                           "-" + version + " package from specs")
         raise Exception("Invalid package: " + package + "-" + version)
 
     def getBuildRequiresForPackage(self, package, version):
         buildRequiresList=[]
4ed339b4
         for pkg in self._getSpecObjField(package, version, field=lambda x : x.buildRequires):
f93ef2b0
             properVersion = self._getProperVersion(pkg)
             buildRequiresList.append(pkg.package+"-"+properVersion)
         return buildRequiresList
 
8f56b626
     def getExtraBuildRequiresForPackage(self, package, version):
         packages=[]
         for pkg in self._getSpecObjField(package, version, field=lambda x : x.extraBuildRequires):
             # no version deps for publishrpms - use just name
             packages.append(pkg.package)
         return packages
 
a007b861
     def getBuildRequiresNativeForPackage(self, package, version):
         packages=[]
         for pkg in self._getSpecObjField(package, version, field=lambda x : x.buildRequiresNative):
             properVersion = self._getProperVersion(pkg)
             packages.append(pkg.package+"-"+properVersion)
         return packages
 
f93ef2b0
     def getBuildRequiresForPkg(self, pkg):
         package, version = StringUtils.splitPackageNameAndVersion(pkg)
         return self.getBuildRequiresForPackage(package, version)
 
     # Returns list of [ "pkg1-vers1", "pkg2-vers2",.. ]
     def getRequiresAllForPackage(self, package, version):
         requiresList=[]
4ed339b4
         for pkg in self._getSpecObjField(package, version, field=lambda x : x.installRequires):
f93ef2b0
             properVersion = self._getProperVersion(pkg)
             requiresList.append(pkg.package+"-"+properVersion)
         return requiresList
 
     def getRequiresAllForPkg(self, pkg):
         package, version = StringUtils.splitPackageNameAndVersion(pkg)
         return self.getRequiresAllForPackage(package, version)
 
     def getRequiresForPackage(self, package, version):
         requiresList=[]
4ed339b4
         for specObj in self.getSpecObjects(package):
f93ef2b0
             if specObj.version == version:
                 if package in specObj.installRequiresPackages:
                     requiresPackages = specObj.installRequiresPackages[package]
                     for pkg in requiresPackages:
                         properVersion = self._getProperVersion(pkg)
                         requiresList.append(pkg.package+"-"+properVersion)
                 return requiresList
f8f09a53
         self.logger.error("Could not find " + package +
f93ef2b0
                           "-" + version + " package from specs")
         raise Exception("Invalid package: " + package + "-" + version)
 
     def getRequiresForPkg(self, pkg):
         package, version = StringUtils.splitPackageNameAndVersion(pkg)
         return self.getRequiresForPackage(package, version)
 
     def getCheckBuildRequiresForPackage(self, package, version):
         checkBuildRequiresList=[]
4ed339b4
         checkBuildRequiresPackages = self._getSpecObjField(package, version, field=lambda x : x.checkBuildRequires)
f93ef2b0
         for pkg in checkBuildRequiresPackages:
             properVersion = self._getProperVersion(pkg)
             checkBuildRequiresList.append(pkg.package+"-"+properVersion)
         return checkBuildRequiresList
5f40784b
 
4ed339b4
     # Returns list of SpecObjects for given subpackage name
     def getSpecObjects(self, package):
4a93976f
         specName=self.getSpecName(package)
         return self.mapSpecObjects[specName]
 
e45f5730
     def getPkgNamesFromObj(self, objlist):
         listPkgName=[]
f93ef2b0
         for name in objlist:
e45f5730
                 listPkgName.append(name.package)
         return listPkgName
 
f93ef2b0
     def getRelease(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.release)
5062126c
 
f93ef2b0
     def getVersions(self, package):
         versions=[]
4ed339b4
         for specObj in self.getSpecObjects(package):
f93ef2b0
             versions.append(specObj.version)
         return versions
5062126c
 
f93ef2b0
     def getHighestVersion(self, package):
4ed339b4
         return self.getSpecObjects(package)[0].version
5062126c
 
f93ef2b0
     def getBuildArch(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.buildarch[package])
3cc43c92
 
f93ef2b0
     def getSpecFile(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.specFile)
5062126c
 
f93ef2b0
     def getPatches(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.listPatches)
3cc43c92
 
f93ef2b0
     def getSources(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.listSources)
37022ec3
 
f93ef2b0
     def getSHA1(self, package, version, source):
         return self._getSpecObjField(package, version, field=lambda x : x.checksums.get(source))
 
     # returns list of package names (no versions)
     def getPackages(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.listPackages)
 
     def getPackagesForPkg(self, pkg):
29d834bc
         pkgs=[]
f93ef2b0
         package, version = StringUtils.splitPackageNameAndVersion(pkg)
29d834bc
         for p in self.getPackages(package, version):
             pkgs.append(p+"-"+version)
         return pkgs
f93ef2b0
 
     def getRPMPackages(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.listRPMPackages)
adf248d5
 
accc8120
     @staticmethod
5d822c2d
     def compareVersions(p):
         return (StrictVersion(p.version))
87815216
 
     def getSpecName(self, package):
         if package in self.mapPackageToSpec:
             specName = self.mapPackageToSpec[package]
5d822c2d
             if specName in self.mapSpecObjects:
51e6babb
                 return specName
26b55679
         self.logger.error("Could not find " + package + " package from specs")
87815216
         raise Exception("Invalid package:" + package)
b5e09fac
 
87815216
     def isRPMPackage(self, package):
         if package in self.mapPackageToSpec:
             specName = self.mapPackageToSpec[package]
5d822c2d
             if specName in self.mapSpecObjects:
af3575c9
                 return True
         return False
b5e09fac
 
f93ef2b0
     def getSecurityHardeningOption(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.securityHardening)
cb4e8710
 
f93ef2b0
     def isCheckAvailable(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.isCheckAvailable)
b5e09fac
 
97a9151c
     def getListPackages(self):
5d822c2d
         return list(self.mapSpecObjects.keys())
5062126c
 
f93ef2b0
     def getURL(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.url)
5062126c
 
f93ef2b0
     def getSourceURL(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.sourceurl)
5062126c
 
f93ef2b0
     def getLicense(self, package, version):
         return self._getSpecObjField(package, version, field=lambda x : x.license)
 
     # Converts "glibc-devel-2.28" into "glibc-2.28"
     def getBasePkg(self, pkg):
         package, version = StringUtils.splitPackageNameAndVersion(pkg)
         return self.getSpecName(package)+"-"+version
5d822c2d
 
5062126c
 
2820c61a
     def printAllObjects(self):
5d822c2d
         listSpecs = self.mapSpecObjects.keys()
2820c61a
         for spec in listSpecs:
cfd85ba2
             for specObj in self.mapSpecObjects[spec]:
26b55679
                 self.logger.debug("-----------Spec:"+specObj.name+"--------------")
                 self.logger.debug("Version:"+specObj.version)
                 self.logger.debug("Release:"+specObj.release)
                 self.logger.debug("SpecFile:"+specObj.specFile)
                 self.logger.debug("Source Files")
                 self.logger.debug(specObj.listSources)
                 self.logger.debug("Patch Files")
                 self.logger.debug(specObj.listPatches)
                 self.logger.debug("List RPM packages")
                 self.logger.debug(specObj.listPackages)
                 self.logger.debug("Build require packages")
4ed339b4
                 self.logger.debug(self.getPkgNamesFromObj(specObj.buildRequires))
26b55679
                 self.logger.debug("install require packages")
4ed339b4
                 self.logger.debug(self.getPkgNamesFromObj(specObj.installRequires))
26b55679
                 self.logger.debug(specObj.installRequiresPackages)
                 self.logger.debug("security_hardening: " + specObj.securityHardening)
a007b861
                 self.logger.debug("BuildArch: " + str(specObj.buildarch))
26b55679
                 self.logger.debug("------------------------------------------------")
5e29a499
 
accc8120
 
45c9260c
 class SPECS(object):
     __instance = None
a007b861
     specData = {}
45c9260c
 
     @staticmethod
a007b861
     def getData(arch=None):
         if not arch:
             arch=constants.currentArch
 
45c9260c
         """ Static access method. """
87815216
         if SPECS.__instance is None:
45c9260c
             SPECS()
a007b861
         return SPECS.__instance.specData[arch]
45c9260c
 
     def __init__(self):
         """ Virtually private constructor. """
87815216
         if SPECS.__instance is not None:
45c9260c
             raise Exception("This class is a singleton!")
         else:
             SPECS.__instance = self
         self.initialize()
 
     def initialize(self):
343d89e8
         # Preparse some files
a0abf4dd
 
accc8120
         # adding kernelversion rpm macro
a007b861
         spec = SpecParser(constants.specPath + "/linux/linux.spec", constants.buildArch)
4ed339b4
         defPkg = spec.packages.get('default')
         kernelversion = defPkg.version
87815216
         constants.addMacro("KERNEL_VERSION", kernelversion)
45c9260c
 
accc8120
         # adding kernelrelease rpm macro
4ed339b4
         kernelrelease = defPkg.release
87815216
         constants.addMacro("KERNEL_RELEASE", kernelrelease)
45c9260c
 
accc8120
         # adding kernelsubrelease rpm macro
87815216
         a, b, c = kernelversion.split(".")
         kernelsubrelease = ('%02d%02d%03d%03d' % (int(a),
                                                   int(b), int(c),
                                                   int(kernelrelease.split('.')[0])))
45c9260c
         if kernelsubrelease:
87815216
             kernelsubrelease = "." + kernelsubrelease
             constants.addMacro("kernelsubrelease", kernelsubrelease)
45c9260c
 
343d89e8
         # Full parsing
a007b861
         self.specData[constants.buildArch] = SpecData(constants.buildArch,
                                                       constants.logPath,
                                                       constants.specPath)
 
         if constants.buildArch != constants.targetArch:
             self.specData[constants.targetArch] = SpecData(constants.targetArch,
                                                            constants.logPath,
                                                            constants.specPath)