from SpecUtils import Specutils
from StringUtils import StringUtils
import operator
import os
import collections
import Queue
import json
class SerializableSpecObject(object):
def __init__(self):
self.listPackages=[]
self.name=""
self.version=""
self.release=""
self.buildRequirePackages=[]
self.installRequiresAllPackages=[]
self.installRequiresPackages={}
self.specFile=""
self.listSources=[]
self.listPatches=[]
self.securityHardening=""
class SerializedSpecObjects(object):
def __init__(self, inputDataDir, stageDir):
self.mapSerializableSpecObjects={}
self.mapPackageToSpec={}
self.jsonFilesOutPath = stageDir + "/common/data/"
self.inputDataDir = inputDataDir
def findTotalRequires(self, allDeps, depQue, parent, displayOption):
while not depQue.empty():
specPkg = depQue.get()
specName = self.getSpecName(specPkg)
specObj = self.mapSerializableSpecObjects[specName]
for depPkg in specObj.installRequiresPackages[specPkg]:
if True == allDeps.has_key(depPkg):
if(allDeps[depPkg] < allDeps[specPkg] + 1):
allDeps[depPkg] = allDeps[specPkg] + 1
parent[depPkg] = specPkg
self.updateLevels(allDeps, depPkg, parent, allDeps[depPkg])
else:
allDeps[depPkg] = allDeps[specPkg] + 1
parent[depPkg] = specPkg
depQue.put(depPkg)
def printTree(self, allDeps, children, curParent , depth):
if (children.has_key(curParent)):
for child in children[curParent]:
print "\t" * depth, child
self.printTree(allDeps, children, child, depth+1)
def get_all_package_names(self, jsonFilePath):
base_path = os.path.dirname(jsonFilePath)
jsonData = open(jsonFilePath)
option_list_json = json.load(jsonData)
jsonData.close()
packages = option_list_json["packages"]
return packages
def updateLevels(self, allDeps, inPkg, parent, level):
specName = self.getSpecName(inPkg)
specObj = self.mapSerializableSpecObjects[specName]
for depPkg in specObj.installRequiresPackages[inPkg]:
if (allDeps.has_key(depPkg) and allDeps[depPkg] < level + 1):
allDeps[depPkg] = level + 1
parent[depPkg] = inPkg
self.updateLevels(allDeps, depPkg, parent, allDeps[depPkg])
def readSpecsAndConvertToSerializableObjects(self, specFilesPath, inputType, inputValue, displayOption):
children = {}
listSpecFiles=[]
whoNeedsList=[]
independentRPMS=[] # list of all RPMS not built from photon and that must be blindly copied.
allDeps={}
parent={}
depQue = Queue.Queue()
packageFound = False
self.getListSpecFiles(listSpecFiles,specFilesPath)
for specFile in listSpecFiles:
spec=Specutils(specFile)
specName=spec.getBasePackageName()
specObj=SerializableSpecObject()
specObj.name=specName
specObj.buildRequirePackages=spec.getBuildRequiresAllPackages()
specObj.installRequiresAllPackages=spec.getRequiresAllPackages()
specObj.listPackages=spec.getPackageNames()
specObj.specFile=specFile
specObj.version=spec.getVersion()
specObj.release=spec.getRelease()
specObj.listSources=spec.getSourceNames()
specObj.listPatches=spec.getPatchNames()
specObj.securityHardening=spec.getSecurityHardeningOption()
for specPkg in specObj.listPackages:
specObj.installRequiresPackages[specPkg]=spec.getRequires(specPkg)
if (inputType == "pkg" and inputValue == specPkg): # all the first level dependencies to a dictionary and queue
packageFound = True
for depPkg in specObj.installRequiresPackages[specPkg]:
if False == allDeps.has_key(depPkg):
allDeps[depPkg] = 0
parent[depPkg] = ""
depQue.put(depPkg)
if (inputType == "who-needs" and (inputValue in specObj.installRequiresPackages[specPkg])):
whoNeedsList.append(specPkg)
self.mapPackageToSpec[specPkg]=specName
self.mapSerializableSpecObjects[specName]=specObj
# Generate dependencies for individual packages
if (inputType == "pkg"):
if (packageFound == True):
self.findTotalRequires(allDeps, depQue, parent, displayOption)
else:
print "No spec file builds a package named",inputValue
return
# Generate dependencies for all packages in the given JSON input file
elif (inputType == "json"):
filePath = self.inputDataDir +"/"+ inputValue
data = self.get_all_package_names(filePath)
for pkg in data:
if False == allDeps.has_key(pkg):
spName = self.getSpecName(pkg)
if(spName != None):
allDeps[pkg] = 0
parent[pkg] = ""
depQue.put(pkg)
self.findTotalRequires(allDeps, depQue, parent, displayOption)
else:
independentRPMS.append(pkg);
#Generating the list of packages that requires the given input package at install time
elif (inputType == "who-needs"):
print whoNeedsList
return
# construct the sorted list of all packages (sorted by dependency)
sortedList = []
for elem in sorted(allDeps.items(), key=operator.itemgetter(1), reverse=True):
sortedList.append(elem[0])
sortedList.extend(independentRPMS)
# construct all children nodes
if (displayOption == "tree"):
for k, v in parent.iteritems():
children.setdefault(v, []).append(k)
if(inputType == "json"):
print "Dependency Mappings for", inputValue, ":", "\n----------------------------------------------------",children
print "----------------------------------------------------"
if (children.has_key("")):
for child in children[""]:
print child
self.printTree(allDeps, children, child, 1)
for pkg in independentRPMS:
print pkg
print "******************",len(sortedList), "packages in total ******************"
else:
if (inputType == "pkg" and len(children) > 0):
print "cyclic dependency detected, mappings: \n",children
# To display a flat list of all packages
elif(displayOption == "list"):
print sortedList
# To generate a new JSON file based on given input json file
elif(displayOption == "json" and inputType == "json"):
d = {}
d['packages'] = sortedList
outFilePath = self.jsonFilesOutPath + inputValue
with open(outFilePath, 'wb') as outfile:
json.dump(d, outfile)
def getListSpecFiles(self,listSpecFiles,path):
for dirEntry in os.listdir(path):
dirEntryPath = os.path.join(path, dirEntry)
if os.path.isfile(dirEntryPath) and dirEntryPath.endswith(".spec"):
listSpecFiles.append(dirEntryPath)
elif os.path.isdir(dirEntryPath):
self.getListSpecFiles(listSpecFiles,dirEntryPath)
def getBuildRequiresForPackage(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].buildRequirePackages
def getRequiresForPackage(self, package):
specName=self.getSpecName(package)
if self.mapSerializableSpecObjects[specName].installRequiresPackages.has_key(package):
return self.mapSerializableSpecObjects[specName].installRequiresPackages[package]
return None
def getRelease(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].release
def getVersion(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].version
def getSpecFile(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].specFile
def getPatches(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].listPatches
def getSources(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].listSources
def getPackages(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].listPackages
def getSpecName(self,package):
if self.mapPackageToSpec.has_key(package):
specName=self.mapPackageToSpec[package]
if self.mapSerializableSpecObjects.has_key(specName):
return specName
else:
print "SpecDeps: Could not able to find " + package + " package from specs"
raise Exception("Invalid package:" + package)
else:
return None
def isRPMPackage(self,package):
if self.mapPackageToSpec.has_key(package):
specName=self.mapPackageToSpec[package]
if self.mapSerializableSpecObjects.has_key(specName):
return True
return False
def getSecurityHardeningOption(self, package):
specName=self.getSpecName(package)
return self.mapSerializableSpecObjects[specName].securityHardening
def getSpecDetails(self, name):
print self.mapSerializableSpecObjects[name].installRequiresAllPackages