Index: smart/channels/yast2.py =================================================================== --- smart/channels/yast2.py (.../trunk) (revisão 0) +++ smart/channels/yast2.py (.../branches/yast2-channel) (revisão 696) @@ -0,0 +1,119 @@ +# +# Copyright (c) 2004 Conectiva, Inc. +# +# Written by Mauricio Teixeira +# +# 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.backends.rpm.yast2 import YaST2Loader +from smart.util.filetools import getFileDigest +from smart.const import SUCCEEDED, FAILED, NEVER +from smart.channel import PackageChannel +from smart import * +import posixpath +import tempfile +import commands +import os + +class YaST2Channel(PackageChannel): + def __init__(self, baseurl, *args): + super(YaST2Channel, self).__init__(*args) + self._baseurl = baseurl + + def getCacheCompareURLs(self): + return [posixpath.join(self._baseurl, "media.1/media")] + + def getFetchSteps(self): + return 4 + + def __fetchFile(self, file, fetcher, progress): + fetcher.reset() + item = fetcher.enqueue(file) + fetcher.run(progress=progress) + failed = item.getFailedReason() + if failed: + progress.add(self.getFetchSteps()-1) + progress.show() + if fetcher.getCaching() is NEVER: + lines = [_("Failed acquiring information for '%s':") % self, + "%s: %s" % (item.getURL(), failed)] + raise Error, "\n".join(lines) + return False + return item + + def fetch(self, fetcher, progress): + + # Fetch media information file + # This file contains the timestamp info + # that says if the repository has changed + fetchitem = posixpath.join(self._baseurl, "media.1/media") + fetched = self.__fetchFile(fetchitem, fetcher, progress) + if not fetched: return False + + digest = getFileDigest(fetched.getTargetPath()) + #if digest == self._digest and getattr(self, "force-yast", False): + if digest == self._digest: + return True + self.removeLoaders() + + # Find location of description files + fetchitem = posixpath.join(self._baseurl, "content") + fetched = self.__fetchFile(fetchitem, fetcher, progress) + if not fetched: return False + self.removeLoaders() + descrdir = "suse/setup/descr" + datadir = "RPMS" + for line in open(fetched.getTargetPath()): + if line.startswith("DESCRDIR"): descrdir = line[9:-1] + if line.startswith("DATADIR"): datadir = line[8:-1] + + # Fetch package information (req, dep, prov, etc) + fetchitem = posixpath.join(self._baseurl, + (("%s/packages") % descrdir)) + fetched = self.__fetchFile(fetchitem, fetcher, progress) + if not fetched: return False + self.removeLoaders() + pkginfofile = fetched.getTargetPath() + if open(pkginfofile).read(9) == "=Ver: 2.0": + fetchitem = posixpath.join(self._baseurl, + (("%s/packages.en") % descrdir)) + fetched = self.__fetchFile(fetchitem, fetcher, progress) + if not fetched or open(fetched.getTargetPath()).read(9) != "=Ver: 2.0": + raise Error, "YaST2 package descriptions not loaded." + loader = YaST2Loader(self._baseurl, datadir, pkginfofile) + else: + pkgdescfile = fetched.getTargetPath() + loader = YaST2Loader(self._baseurl, datadir, pkginfofile, pkgdescfile) + loader.setChannel(self) + self._loaders.append(loader) + else: + raise Error, _("Invalid package file format. Invalid header found.") + + self._digest = digest + + return True + +def create(alias, data): + return YaST2Channel(data["baseurl"], + data["type"], + alias, + data["name"], + data["manual"], + data["removable"], + data["priority"]) + +# vim:ts=4:sw=4:et Index: smart/channels/yast2_info.py =================================================================== --- smart/channels/yast2_info.py (.../trunk) (revisão 0) +++ smart/channels/yast2_info.py (.../branches/yast2-channel) (revisão 696) @@ -0,0 +1,35 @@ +# +# Copyright (c) 2004 Conectiva, Inc. +# +# Written by Mauricio Teixeira +# +# 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 import _ + +kind = "package" + +name = _("YaST2 Repository") + +description = _(""" +Repositories created for YaST2. +""") + +fields = [("baseurl", _("Base URL"), str, None, + _("Base URL of YaST2 repository, where directory.yast is located.")), + ("medias", _("Medias"), str, "", + _("Space separated list of medias. (NOT IN USE YET)"))] Index: smart/backends/rpm/yast2.py =================================================================== --- smart/backends/rpm/yast2.py (.../trunk) (revisão 0) +++ smart/backends/rpm/yast2.py (.../branches/yast2-channel) (revisão 696) @@ -0,0 +1,299 @@ +# +# Copyright (c) 2004 Conectiva, Inc. +# +# Written by Mauricio Teixeira +# +# 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.backends.rpm.rpmver import splitarch +from smart.cache import PackageInfo, Loader +from smart.backends.rpm.base import * +from smart import * +import posixpath +import locale +import os + +class YaST2PackageInfo(PackageInfo): + def __init__(self, package, loader, info): + PackageInfo.__init__(self, package) + self._loader = loader + self._info = info + + def getURLs(self): + version, arch = splitarch(self._package.version) + return [posixpath.join(self._loader._baseurl, + self._loader._datadir, arch, + self._info.get("filename"))] + + def getInstalledSize(self): + return int(self._info.get("instsize")) + + def getSize(self, url): + return int(self._info.get("size")) + + def getSummary(self): + return self._info.get("summary", "") + + def getDescription(self): + return self._info.get("description", "") + + def getGroup(self): + return self._info.get("group", "") + +class YaST2Loader(Loader): + + __stateversion__ = Loader.__stateversion__+1 + + def __init__(self, baseurl, datadir, pkginfofile, pkgdescfile=None): + Loader.__init__(self) + self._baseurl = baseurl + self._datadir = datadir + self._pkginfofile = pkginfofile + self._pkgdescfile = pkgdescfile + + def getInfo(self, pkg): + return YaST2PackageInfo(pkg, self, pkg.loaders[self]) + + def getLoadSteps(self): + pkgfile = open(self._pkginfofile) + total = 0 + for line in pkgfile: + if line.startswith("=Pkg: "): + total += 1 + pkgfile.close() + return total + + def getInfoEntity(self, tag): + data = [] + found = False + for line in self._pkgentry: + if line.startswith("+" + tag + ":"): + found = True + continue + elif line.startswith("-" + tag + ":"): + break + elif line[:7] in ("rpmlib(", "config("): + continue + elif found == True: + parts = line.split(" ") + if len(parts) == 1: + data.append((line, None, None)) + else: + data.append((parts[0], parts[1], parts[2])) + return data + + def stripTags(self, s): + # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440481 + # this list is neccesarry because chk() would otherwise not know + # that intag in stripTags() is ment, and not a new intag variable in chk(). + intag = [False] + def chk(c): + if intag[0]: + intag[0] = (c != '>') + return False + elif c == '<': + intag[0] = True + return False + return True + return ''.join(c for c in s if chk(c)) + + def readPkgSummDesc(self, entryname): + summary = description = "" + if self._pkgdescfile and self._pkgoffsets.has_key(entryname): + self._descfile.seek((self._pkgoffsets[entryname] + 1)) + summary = self._descfile.readline()[5:-1] + description = "" + # WARNING - this could cause an infinite loop! + # We need to find a better way to do it! + while 1: + line = self._descfile.readline() + if line.startswith("+Des:") or line.startswith("