1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-11-14 08:16:15 +01:00
github.com_openSUSE_osc/osc/util/repodata.py

191 lines
5.9 KiB
Python
Raw Normal View History

"""Module for reading repodata directory (created with createrepo) for package
information instead of scanning individual rpms."""
# standard modules
import gzip
import os.path
# cElementTree can be standard or 3rd-party depending on python version
try:
from xml.etree import cElementTree as ET
except ImportError:
import cElementTree as ET
# project modules
import osc.util.rpmquery
import osc.util.packagequery
def namespace(name):
return "{http://linux.duke.edu/metadata/%s}" % name
OPERATOR_BY_FLAGS = {
"EQ" : "=",
"LE" : "<=",
"GE" : ">=",
"LT" : "<",
"GT" : ">"
}
def primaryPath(directory):
"""Returns path to the primary repository data file.
2010-02-28 02:30:13 +01:00
@param directory repository directory that contains the repodata subdirectory
@return str path to primary repository data file
@raise IOError if repomd.xml contains no primary location
"""
metaDataPath = os.path.join(directory, "repodata", "repomd.xml")
elementTree = ET.parse(metaDataPath)
root = elementTree.getroot()
2010-02-28 02:30:13 +01:00
for dataElement in root:
if dataElement.get("type") == "primary":
locationElement = dataElement.find(namespace("repo") + "location")
# even though the repomd.xml file is under repodata, the location a
# attribute is relative to parent directory (directory).
primaryPath = os.path.join(directory, locationElement.get("href"))
break
else:
raise IOError("'%s' contains no primary location" % metaDataPath)
2010-02-28 02:30:13 +01:00
return primaryPath
def queries(directory):
"""Returns a list of RepoDataQueries constructed from the repodata under
the directory.
2010-02-28 02:30:13 +01:00
@param directory path to a repository directory (parent directory of
repodata directory)
@return list of RepoDataQueryResult instances
@raise IOError if repomd.xml contains no primary location
"""
path = primaryPath(directory)
2010-02-28 02:30:13 +01:00
gunzippedPrimary = gzip.GzipFile(path)
elementTree = ET.parse(gunzippedPrimary)
root = elementTree.getroot()
2010-02-28 02:30:13 +01:00
packageQueries = []
for packageElement in root:
packageQuery = RepoDataQueryResult(directory, packageElement)
packageQueries.append(packageQuery)
2010-02-28 02:30:13 +01:00
return packageQueries
class RepoDataQueryResult(osc.util.packagequery.PackageQueryResult):
"""PackageQueryResult that reads in data from the repodata directory files."""
2010-02-28 02:30:13 +01:00
def __init__(self, directory, element):
"""Creates a RepoDataQueryResult from the a package Element under a metadata
Element in a primary.xml file.
2010-02-28 02:30:13 +01:00
@param directory repository directory path. Used to convert relative
paths to full paths.
@param element package Element
"""
self.__directory = os.path.abspath(directory)
self.__element = element
2010-02-28 02:30:13 +01:00
def __formatElement(self):
return self.__element.find(namespace("common") + "format")
2010-02-28 02:30:13 +01:00
def __parseEntry(self, element):
entry = element.get("name")
flags = element.get("flags")
2010-02-28 02:30:13 +01:00
if flags is not None:
version = element.get("ver")
operator = OPERATOR_BY_FLAGS[flags]
entry += " %s %s" % (operator, version)
2010-02-28 02:30:13 +01:00
release = element.get("rel")
if release is not None:
2010-02-05 15:14:48 +01:00
entry += "-%s" % release
2010-02-28 02:30:13 +01:00
return entry
2010-02-28 02:30:13 +01:00
def __parseEntryCollection(self, collection):
formatElement = self.__formatElement()
collectionElement = formatElement.find(namespace("rpm") + collection)
2010-02-28 02:30:13 +01:00
entries = []
if collectionElement is not None:
for entryElement in collectionElement.findall(namespace("rpm") +
"entry"):
entry = self.__parseEntry(entryElement)
entries.append(entry)
2010-02-28 02:30:13 +01:00
return entries
2010-02-28 02:30:13 +01:00
def __versionElement(self):
return self.__element.find(namespace("common") + "version")
2010-02-28 02:30:13 +01:00
def arch(self):
return self.__element.find(namespace("common") + "arch").text
2010-02-28 02:30:13 +01:00
def description(self):
return self.__element.find(namespace("common") + "description").text
2010-02-28 02:30:13 +01:00
def distribution(self):
return None
2010-02-28 02:30:13 +01:00
def epoch(self):
return self.__versionElement().get("epoch")
2010-02-28 02:30:13 +01:00
def name(self):
return self.__element.find(namespace("common") + "name").text
2010-02-28 02:30:13 +01:00
def path(self):
locationElement = self.__element.find(namespace("common") + "location")
relativePath = locationElement.get("href")
absolutePath = os.path.join(self.__directory, relativePath)
2010-02-28 02:30:13 +01:00
return absolutePath
2010-02-28 02:30:13 +01:00
def provides(self):
return self.__parseEntryCollection("provides")
2010-02-28 02:30:13 +01:00
def release(self):
return self.__versionElement().get("rel")
2010-02-28 02:30:13 +01:00
def requires(self):
return self.__parseEntryCollection("requires")
2010-02-28 02:30:13 +01:00
def conflicts(self):
return self.__parseEntryCollection('conflicts')
def obsoletes(self):
return self.__parseEntryCollection('obsoletes')
def recommends(self):
return self.__parseEntryCollection('recommends')
def suggests(self):
return self.__parseEntryCollection('suggests')
def supplements(self):
return self.__parseEntryCollection('supplements')
def enhances(self):
return self.__parseEntryCollection('enhances')
def canonname(self):
return osc.util.rpmquery.RpmQuery.filename(self.name(), None,
self.version(), self.release(), self.arch())
def gettag(self, tag):
# implement me, if needed
return None
def vercmp(self, other):
res = osc.util.rpmquery.RpmQuery.rpmvercmp(str(self.epoch()), str(other.epoch()))
if res != 0:
return res
res = osc.util.rpmquery.RpmQuery.rpmvercmp(self.version(), other.version())
if res != 0:
return res
res = osc.util.rpmquery.RpmQuery.rpmvercmp(self.release(), other.release())
return res
2010-02-28 02:30:13 +01:00
def version(self):
return self.__versionElement().get("ver")