diff --git a/pisi/specfile.py b/pisi/specfile.py index fc40b435..cf0b3ad8 100644 --- a/pisi/specfile.py +++ b/pisi/specfile.py @@ -101,7 +101,7 @@ class Update: s += ", type=" + self.type return s - + class Path: s_Path = [xmlfile.String, xmlfile.mandatory] @@ -112,6 +112,7 @@ class Path: s += ", type=" + self.fileType return s + class ComarProvide: s_om = [xmlfile.String, xmlfile.mandatory] diff --git a/pisi/specfileold.py b/pisi/specfileold.py deleted file mode 100644 index d47ff28c..00000000 --- a/pisi/specfileold.py +++ /dev/null @@ -1,504 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program 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. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Gurer Ozen -# Baris Metin -# History: -# Baris wrote the first version, then Baris and Eray did -# several revisions of it. It was modified in accordance -# with Gurer's observations about poor error handling. - - -""" -Specfile module is our handler for PSPEC files. PSPEC (PISI SPEC) -files are specification files for PISI source packages. This module -provides read and write access to PSPEC files. -""" - -# standard python modules -from os.path import basename - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# pisi modules -import pisi -from pisi.xmlext import * -from pisi.xmlfile import XmlFile -import pisi.xmlfile as xmlfile -from pisi.dependency import DepInfo -from pisi.util import Checks -import pisi.util as util -import pisi.context as ctx - -class PackagerInfo: - def __init__(self, node = None): - if node: - self.name = getNodeText(getNode(node, "Name")) - self.email = getNodeText(getNode(node, "Email")) - else: - self.name = None - self.email = None - - def elt(self, xml): - node = xml.newNode("Packager") - xml.addTextNodeUnder(node, "Name", self.name) - xml.addTextNodeUnder(node, "Email", self.email) - return node - - def has_errors(self): - err = Checks() - err.has_tag(self.name, "Packager", "Name") - err.has_tag(self.email, "Packager", "Email") - return err.list - - def __str__(self): - s = "%s <%s>" % (self.name, self.email) - return s - -class AdditionalFileInfo: - def __init__(self, node = None): - if node: - self.filename = getNodeText(node) - self.target = getNodeAttribute(node, "target") - self.permission = getNodeAttribute(node, "permission") - - def elt(self, xml): - node = xml.newNode("AdditionalFile") - xml.addText(node, self.filename) - node.setAttribute("target", self.target) - if self.permission: - node.setAttribute("permission", self.permission) - - def has_errors(self): - err = Checks() - if not self.filename: - err.add(_("AdditionalFile should have file name string")) - if not self.target: - err.add(_("AdditionalFile should have a target attribute")) - return err.list - - def __str__(self): - s = "->".join(self.filename, self.target) - s += s + '(' + self.permission + ')' - return s - -class PatchInfo: - def __init__(self, node = None): - if node: - self.filename = getNodeText(node) - self.compressionType = getNodeAttribute(node, "compressionType") - self.level = getNodeAttribute(node, "level") - self.target = getNodeAttribute(node, "target") - else: - self.compressionType = None - if not self.level: - self.level = 0 - else: - self.level = int(self.level) - if not self.target: - self.target = '' - - def elt(self, xml): - node = xml.newNode("Patch") - xml.addText(node, self.filename) - if self.compressionType: - node.setAttribute("compressionType", self.compressionType) - if self.level: - node.setAttribute("level", str(self.level)) - if self.target: - node.setAttribute("target", self.target) - return node - - def has_errors(self): - if not self.filename: - return [ _("Patch should have a filename string") ] - return [] - - def __str__(self): - s = self.filename - s += ' (' + self.compressionType + ')' - s += ' level:' + self.level - return s - - -class UpdateInfo: - def __init__(self, node = None): - if node: - self.release = getNodeAttribute(node, "release") - self.type = getNodeAttribute(node, "type") - self.date = getNodeText(getNode(node, "Date")) - self.version = getNodeText(getNode(node, "Version")) - self.comment = getNodeText(getNode(node, "Comment")) - self.name = getNodeText(getNode(node, "Name")) - self.email = getNodeText(getNode(node, "Email")) - else: - self.type = None - - def elt(self, xml): - node = xml.newNode("Update") - node.setAttribute("release", self.release) - xml.addTextNodeUnder(node, "Date", self.date) - xml.addTextNodeUnder(node, "Version", self.version) - if self.comment: - xml.addTextNodeUnder(node, "Comment", self.comment) - if self.name: - xml.addTextNodeUnder(node, "Name", self.name) - if self.email: - xml.addTextNodeUnder(node, "Email", self.email) - if self.type: - node.setAttribute("type", self.type) - return node - - def has_errors(self): - err = Checks() - if not self.release: - err.add(_("Update must have a release attribute")) - err.has_tag(self.date, "Update", "Date") - #err.has_tag(self.version, "Update", "Version") - return err.list - - def __str__(self): - return "rel=%s, date=%s, ver=%s, type=%s" % ( - self.release, self.date, self.version, self.type) - -class PathInfo: - def __init__(self, node = None): - if node: - self.pathname = getNodeText(node) - self.fileType = getNodeAttribute(node, "fileType") - if not self.fileType: - self.fileType = "other" - - def elt(self, xml): - node = xml.newNode("Path") - xml.addText(node, self.pathname) - node.setAttribute("fileType", self.fileType) - return node - - def has_errors(self): - if not self.pathname: - return [ _("Path tag should have a name string") ] - return [] - - def __str__(self): - s = self.pathname - s += ", type=" + self.fileType - return s - -class ComarProvide: - def __init__(self, node = None): - if node: - self.om = getNodeText(node) - self.script=getNodeAttribute(node, "script") - - def elt(self, xml): - node = xml.newNode("COMAR") - xml.addText(node, self.om) - node.setAttribute("script", self.script) - return node - - def has_errors(self): - if not self.om or not self.script: - return [ _("COMAR provide should have something :)") ] - return [] - - def __str__(self): - s = self.script - s += ' (' + self.om + ')' - return s - -class SourceInfo: - """A structure to hold source information. Source information is - located under tag in PSPEC file.""" - def __init__(self, node = None): - if node: - self.name = getNodeText(node, "Name") - self.homepage = getNodeText(node, "Homepage") - self.packager = PackagerInfo(getNode(node, "Packager")) - self.summary = getNodeText(node, "Summary") - self.description = getNodeText(node, "Description") - self.license = map(getNodeText, getAllNodes(node, "License")) - self.icon = getNodeText(node, "Icon") - self.isa = map(getNodeText, getAllNodes(node, "IsA")) - self.partof = getNodeText(node, "PartOf") - archiveNode = getNode(node, "Archive") - self.archiveUri = getNodeText(archiveNode).strip() - self.archiveName = basename(self.archiveUri) - self.archiveType = getNodeAttribute(archiveNode, "type") - self.archiveSHA1 = getNodeAttribute(archiveNode, - "sha1sum") - patchElts = getAllNodes(node, "Patches/Patch") - self.patches = [PatchInfo(p) for p in patchElts] - buildDepElts = getAllNodes(node, - "BuildDependencies/Dependency") - self.buildDeps = [DepInfo(d) for d in buildDepElts] - - def elt(self, xml): - node = xml.newNode("Source") - xml.addTextNodeUnder(node, "Name", self.name) - if self.homepage: - xml.addTextNodeUnder(node, "Homepage", self.homepage) - node.appendChild(self.packager.elt(xml)) - xml.addTextNodeUnder(node, "Summary", self.summary) - xml.addTextNodeUnder(node, "Description", self.description) - if self.icon: - xml.addTextNodeUnder(node, "Icon", self.icon) - for lic in self.license: - xml.addTextNodeUnder(node, "License", lic) - for isa in self.isa: - xml.addTextNodeUnder(node, "IsA", isa) - xml.addTextNodeUnder(node, "PartOf", self.partof) - archiveNode = xml.addNodeUnder(node, "Archive") - archiveNode.setAttribute("type", self.archiveType) - archiveNode.setAttribute("sha1sum", self.archiveSHA1) - for patch in self.patches: - xml.addNodeUnder(node, "Patches", patch.elt(xml)) - for dep in self.buildDeps: - xml.addNodeUnder(node, "BuildDependencies", dep.elt(xml)) - for update in self.history: - xml.addNodeUnder(node, "History", update.elt(xml)) - return node - - def has_errors(self): - err = Checks() - err.has_tag(self.name, "Source", "Name") - err.has_tag(self.description, "Source", "Description") - err.has_tag(self.summary, "Source", "Summary") - err.has_tag(self.packager, "Source", "Packager") - err.has_tag(self.license, "Source", "License") - if (not self.archiveUri) or (not self.archiveType): - err.add(_("Source archive URI and type should be given")) - if not self.archiveSHA1: - err.add(_("Source archive should have a SHA1 sum")) - - err.join(self.packager.has_errors()) - for patch in self.patches: - err.join(patch.has_errors()) - for dep in self.buildDeps: - err.join(dep.has_errors()) - - return err.list - - -class PackageInfo: - """A structure to hold package information. Package information is - located under tag in PSPEC file. Opposite to Source each - PSPEC file can have more than one Package tag.""" - def __init__(self, node = None): - if node: - self.name = getNodeText(node, "Name") - self.summary = getNodeText(node, "Summary") - self.description = getNodeText(node, "Description") - self.isa = map(getNodeText, getAllNodes(node, "IsA")) - self.partof = getNodeText(node, "PartOf") - self.license = map(getNodeText, getAllNodes(node, "License")) - self.icon = getNodeText(node, "Icon") - rtDepElts = getAllNodes(node, "RuntimeDependencies/Dependency") - self.runtimeDeps = [DepInfo(x) for x in rtDepElts] - self.paths = [PathInfo(x) for x in getAllNodes(node, "Files/Path")] - historyElts = getAllNodes(node, "History/Update") - self.history = [UpdateInfo(x) for x in historyElts] - conflElts = getAllNodes(node, "Conflicts/Package") - self.conflicts = map(getNodeText, conflElts) - provComarElts = getAllNodes(node, "Provides/COMAR") - self.providesComar = [ComarProvide(x) for x in provComarElts] - reqComarElts = getAllNodes(node, "Requires/COMAR") - self.requiresComar = map(getNodeText, reqComarElts) - aFilesElts = getAllNodes(node, "AdditionalFiles/AdditionalFile") - self.additionalFiles = [AdditionalFileInfo(f) for f in aFilesElts] - - def elt(self, xml): - node = xml.newNode("Package") - xml.addTextNodeUnder(node, "Name", self.name) - xml.addTextNodeUnder(node, "Summary", self.summary) - xml.addTextNodeUnder(node, "Description", self.description) - if self.icon: - xml.addTextNodeUnder(node, "Icon", self.icon) - for lic in self.license: - xml.addTextNodeUnder(node, "License", lic) - for isa in self.isa: - xml.addTextNodeUnder(node, "IsA", isa) - if self.partof: - xml.addTextNodeUnder(node, "PartOf", self.partof) - for dep in self.runtimeDeps: - xml.addNodeUnder(node, "RuntimeDependencies", dep.elt(xml)) - for path in self.paths: - xml.addNodeUnder(node, "Files", path.elt(xml)) - # FIXME: no need to put full history with comments in metafile.xml - for update in self.history: - xml.addNodeUnder(node, "History", update.elt(xml)) - for conflict in self.conflicts: - xml.addTextNodeUnder(node, "Conflicts/Package", conflict) - for pcomar in self.providesComar: - xml.addNodeUnder(node, "Provides", pcomar.elt(xml)) - for rcomar in self.requiresComar: - xml.addTextNodeUnder(node, "Requires/COMAR", rcomar) - for afile in self.additionalFiles: - xml.addNodeUnder(node, "AdditionalFiles", afile.elt(xml)) - return node - - def has_errors(self): - err = Checks() - err.has_tag(self.name, "Package", "Name") - err.has_tag(self.summary, "Package", "Summary") - err.has_tag(self.description, "Package", "Description") - err.has_tag(self.license, "Package", "License") - if len(self.paths) <= 0: - err.add(_("Package should have some files")) - - for path in self.paths: - err.join(path.has_errors()) - for dep in self.runtimeDeps: - err.join(dep.has_errors()) - for afile in self.additionalFiles: - err.join(afile.has_errors()) - - return err.list - - def __str__(self): - s = _('Name: %s, version: %s, release: %s, build %s') % ( - self.name, self.version, self.release, self.build) - s += _('\nSummary: ') + self.summary - s += _('\nDescription: ') + self.description - s += _('\nComponent: ') + unicode(self.partof) - s += _('\nProvides: ') - for x in self.providesComar: - s += x.om - return s - - def pkg_dir(self): - packageDir = self.name + '-' \ - + self.version + '-' \ - + self.release - - return util.join_path( ctx.config.lib_dir(), packageDir) - - def installable(self): - """calculate if pkg is installable currently""" - import pisi.dependency - deps = self.runtimeDeps - return pisi.dependency.satisfies_dependencies(self.name, deps) - -class SpecFile(XmlFile): - """A class for reading/writing from/to a PSPEC (PISI SPEC) file.""" - - def __init__(self): - XmlFile.__init__(self,"PISI") - - def read(self, filename): - """Read PSPEC file""" - - self.readxml(filename) - - self.source = SourceInfo(self.getNode("Source")) - - historyElts = getAllNodes(self.getNode("History"), "Update") - self.history = [UpdateInfo(x) for x in historyElts] - - # As we have no Source/Version tag we need to get - # the last version and release information - # from the first child of History/Update. And it works :) - self.source.version = self.history[0].version - self.source.release = self.history[0].release - - # find all binary packages - packageElts = self.getAllNodes("Package") - self.packages = [PackageInfo(p) for p in packageElts] - - self.merge_tags() - self.override_tags() - - #FIXME: copy only needed information - # no need to keep full history with comments in metadata.xml - self.source.history = self.history - for p in self.packages: - p.history = self.history - - self.unlink() - - - errs = self.has_errors() - if errs: - e = "" - for x in errs: - e += x + "\n" - raise XmlError(_("File '%s' has errors:\n%s") % (filename, e)) - - def override_tags(self): - """Override tags from Source in Packages. Some tags in Packages - overrides the tags from Source. There is a more detailed - description in documents.""" - - tmp = [] - for pkg in self.packages: - - if not pkg.summary: - pkg.summary = self.source.summary - - if not pkg.description: - pkg.description = self.source.description - - if not pkg.partof: - pkg.partof = self.source.partof - - if not pkg.license: - pkg.license = self.source.license - - if not pkg.icon: - pkg.icon = self.source.icon - - tmp.append(pkg) - - self.packages = tmp - - def merge_tags(self): - """Merge tags from Source in Packages. Some tags in Packages merged - with the tags from Source. There is a more detailed - description in documents.""" - - tmp = [] - for pkg in self.packages: - - if pkg.isa and self.source.isa: - pkg.isa.append(self.source.isa) - elif not pkg.isa and self.source.isa: - pkg.isa = self.source.isa - - tmp.append(pkg) - - self.packages = tmp - - def has_errors(self): - """Return errors of the PSPEC file if there are any.""" - #FIXME: has_errors name is misleading for a function that does - #not just return a boolean value. check() would be better - exa - err = Checks() - err.join(self.source.has_errors()) - if len(self.packages) <= 0: - errs.add(_("There should be at least one Package section")) - for p in self.packages: - err.join(p.has_errors()) - if len(self.history) <= 0: - err.add(_("Source needs some education in History :)")) - for update in self.history: - err.join(update.has_errors()) - return err.list - - def write(self, filename): - """Write PSPEC file""" - self.newDOM() - self.addChild(self.source.elt(self)) - for pkg in self.packages: - self.addChild(pkg.elt(self)) - self.writexml(filename)