Index: smart/channels/rpm_md.py =================================================================== --- smart/channels/rpm_md.py (revision 919) +++ smart/channels/rpm_md.py (arbetskopia) @@ -20,6 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # from smart.backends.rpm.metadata import RPMMetaDataLoader +from smart.backends.rpm.comps import RPMCompsLoader from smart.util.filetools import getFileDigest try: @@ -53,7 +54,7 @@ return [posixpath.join(self._baseurl, "repodata/repomd.xml")] def getFetchSteps(self): - return 3 + return 4 def fetch(self, fetcher, progress): @@ -144,6 +145,25 @@ else: return False + if "group" in info: + fetcher.reset() + item = fetcher.enqueue(info["group"]["url"], + md5=info["group"].get("md5"), + sha=info["group"].get("sha"), + uncomp=False) + fetcher.run(progress=progress) + if item.getStatus() == SUCCEEDED: + localpath = item.getTargetPath() + loader = RPMCompsLoader(localpath, self._baseurl) + loader.setChannel(self) + self._loaders.append(loader) + else: + iface.warning(_("Failed to download. You must fetch channel " + "information to acquire needed group information.\n" + "%s: %s") % (item.getURL(), item.getFailedReason())) + else: + progress.add(1) + self._digest = digest return True Index: smart/backends/rpm/comps.py =================================================================== --- smart/backends/rpm/comps.py (revision 0) +++ smart/backends/rpm/comps.py (revision 0) @@ -0,0 +1,284 @@ +# +# Copyright (c) 2005 Canonical +# Copyright (c) 2004 Conectiva, Inc. +# +# Written by Anders F Bjorklund +# +# This file is part of Smart Package Manager. +# +# Smart Package Manager is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 2 of the License, or (at +# your option) any later version. +# +# Smart Package Manager is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Smart Package Manager; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +from smart.cache import PackageInfo, Loader +from smart.backends.rpm.base import * + +try: + from xml.etree import cElementTree +except ImportError: + try: + import cElementTree + except ImportError: + from smart.util import cElementTree + +from smart import * +import posixpath +import locale +import os + +NS_GROUPS = "http://linux.duke.edu/~skvidal/metadata/groups.dtd" + +BYTESPERPKG = 3000 + +#def nstag(ns, tag): +# return "{%s}%s" % (ns, tag) +def nstag(ns, tag): + return tag + +GROUP_NAME = "Virtual" +GROUP_PREFIX = "^" +GROUP_VERS = "0" +GROUP_ARCH = "noarch" + +def groupname(name): + return "%s%s" % (GROUP_PREFIX, name) + +class RPMCompsPackageInfo(PackageInfo): + + def __init__(self, package, loader, info): + PackageInfo.__init__(self, package) + self._loader = loader + self._info = info + + def getURLs(self): + return [] + + def getInstalledSize(self): + return None + + def getSize(self, url): + return None + + def getMD5(self, url): + return None + + def getSHA(self, url): + return None + + def getDescription(self): + return self._info.get("description", "") + + def getSummary(self): + return self._info.get("name", "") + + def getGroup(self): + return GROUP_NAME + + +class RPMCompsLoader(Loader): + + __stateversion__ = Loader.__stateversion__+3 + + def __init__(self, filename, baseurl): + Loader.__init__(self) + self._filename = filename + self._baseurl = baseurl + + def reset(self): + Loader.reset(self) + + def getInfo(self, pkg): + return RPMCompsPackageInfo(pkg, self, pkg.loaders[self]) + + def getLoadSteps(self): + return os.path.getsize(self._filename)/BYTESPERPKG + + def load(self): + COMPS = nstag(NS_GROUPS, "comps") + GROUP = nstag(NS_GROUPS, "group") + ID = nstag(NS_GROUPS, "id") + DEFAULT = nstag(NS_GROUPS, "default") + USERVISIBLE = nstag(NS_GROUPS, "uservisible") + DISPLAYORDER= nstag(NS_GROUPS, "display_order") + LANGONLY = nstag(NS_GROUPS, "lang_only") + BIARCHONLY = nstag(NS_GROUPS, "biarchonly") + NAME = nstag(NS_GROUPS, "name") + DESCRIPTION = nstag(NS_GROUPS, "description") + GROUPLIST = nstag(NS_GROUPS, "grouplist") + GROUPREQ = nstag(NS_GROUPS, "groupreq") + METAPKG = nstag(NS_GROUPS, "metapkg") + PACKAGELIST = nstag(NS_GROUPS, "packagelist") + PACKAGEREQ = nstag(NS_GROUPS, "packagereq") + + # Prepare progress reporting. + lastoffset = 0 + mod = 0 + progress = iface.getProgress(self._cache) + + # Prepare package information. + name = None + info = {} + reqdict = {} + + # Prepare data useful for the iteration + skip = None + packagelist = False + grouplist = False + queue = [] + + file = open(self._filename) + for event, elem in cElementTree.iterparse(file, ("start", "end")): + tag = elem.tag + + if event == "start": + + if tag == PACKAGELIST: + packagelist = True + if tag == GROUPLIST: + grouplist = True + + queue.append(elem) + + elif event == "end": + + assert queue.pop() is elem + + if skip: + if tag == skip: + skip = None + + elif tag == ID: + name = groupname(elem.text) + + elif tag == NAME: + # TODO multiple languages: only read default language, for now + elang = elem.get('{http://www.w3.org/XML/1998/namespace}lang') + if elem.text and not elang: + info["name"] = elem.text + + elif tag == DESCRIPTION: + # TODO multiple languages: only read default language, for now + elang = elem.get('{http://www.w3.org/XML/1998/namespace}lang') + if elem.text and not elang: + info["description"] = elem.text + + elif tag == DEFAULT: + if elem.text: + info["default"] = elem.text + + elif tag == USERVISIBLE: + if elem.text: + info["uservisible"] = elem.text + + elif tag == DISPLAYORDER: + if elem.text: + info["display_order"] = elem.text + + elif tag == LANGONLY: + if elem.text: + info["lang_only"] = elem.text + + elif tag == GROUPREQ: + ename = elem.text + reqdict[(RPMRequires, groupname(ename), None, None)] = True + + elif tag == METAPKG: + ename = elem.text + etype = elem.get("type") + if etype == None: + reqdict[(RPMRequires, groupname(ename), None, None)] = True + if etype == "optional": + pass + + elif tag == GROUPLIST: + grouplist = False + + elif tag == BIARCHONLY: + if elem.text: + info["biarchonly"] = elem.text + + elif tag == PACKAGEREQ: + ename = elem.text + etype = elem.get("type") + ereq = elem.get("requires") + ebao = elem.get("basearchonly") + if not self.excludeDependency(name, ename): + if etype == "mandatory" or etype == "default": + reqdict[(RPMRequires, ename, None, None)] = True + if etype == "optional" or etype == "conditional": + pass + + elif tag == PACKAGELIST: + packagelist = False + + elif tag == GROUP: + + version = GROUP_VERS + arch = GROUP_ARCH + versionarch = "%s@%s" % (version, arch) + + prvargs = [(RPMProvides, name, None)] + reqargs = reqdict.keys() + upgargs = [] + cnfargs = [] + + pkg = self.buildPackage((RPMPackage, name, versionarch), + prvargs, reqargs, upgargs, cnfargs) + pkg.loaders[self] = info + + # Reset all information. + name = None + reqdict.clear() + + # Do not clear it. pkg.loaders has a reference. + info = {} + + # Update progress + offset = file.tell() + div, mod = divmod(offset-lastoffset+mod, BYTESPERPKG) + lastoffset = offset + progress.add(div) + progress.show() + + elem.clear() + + file.close() + + # exclude some dependencies that doesn't exist (for all arch) on CentOS + def excludeDependency(self, group, req): + if group == groupname("base") and req == "mcelog": + return True + if group == groupname("base") and req == "openCryptoki": + return True + if group == groupname("base") and req == "prctl": + return True + if group == groupname("core") and req == "efibootmgr": + return True + if group == groupname("core") and req == "elilo": + return True + if group == groupname("core") and req == "iprutils": + return True + if group == groupname("core") and req == "ppc64-utils": + return True + if group == groupname("core") and req == "s390utils": + return True + if group == groupname("core") and req == "yaboot": + return True + return False + +def enablePsyco(psyco): + psyco.bind(RPMCompsLoader.load) + +hooks.register("enable-psyco", enablePsyco) + +# vim:ts=4:sw=4:et