Adding side stream changes to Maemian. Working to integrate full upstream libraries...
[maemian] / nokia-lintian / depcheck / relation.py
diff --git a/nokia-lintian/depcheck/relation.py b/nokia-lintian/depcheck/relation.py
new file mode 100644 (file)
index 0000000..b406309
--- /dev/null
@@ -0,0 +1,171 @@
+# This module defines package relationships.
+# It exports two special "version" values: Virtual and Any.
+# A Virtual version never matches a versioned conflict or dependency.
+# An Any version always matches a versioned conflict or dependency.
+
+# Copyright (C) 1998 Richard Braakman
+#
+# This program is free software.  It is distributed 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.
+#
+# This program 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 this program.  If not, you can find it on the World Wide
+# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+
+import string
+
+import version
+
+# The two special "version" values.  All empty lists are unique,
+# so these statements initialize them to unique values.
+Virtual = []
+Any = []
+
+# The basic relationship: a single package name.
+# Its name is stored in the name attribute.
+class SimpleRelation:
+    def __init__(self, package):
+       self.name = package
+
+    def __str__(self):
+       return self.name
+
+    def __repr__(self):
+       return 'SimpleRelation(' + `self.name` + ')'
+
+    def satisfied(self, packagename, version):
+       return packagename == self.name
+
+    def satisfied_by(self, packages):
+       if packages.has_key(self.name):
+           return self.name
+       return None
+
+    def packagenames(self):
+       return [self.name]
+
+# A package name with a version check.
+# The package name is stored in the name attribute.
+# The relation is stored as a string in the relationstring attribute,
+# and as a comparison function in the relation attribute.
+# The version to compare to is stored in the version attribute.
+class VersionedRelation:
+    def __init__(self, package, relation, version):
+       self.name = package
+       self.version = version
+       self.relationstring = relation
+       if relation == '<' or relation == '<=':
+           self.relation = lessthan
+       elif relation == '>' or relation == '>=':
+           self.relation = greaterthan
+       elif relation == '=':
+           self.relation = equalversion
+       elif relation == '>>':
+           self.relation = strictgreater
+       elif relation == '<<':
+           self.relation = strictless
+       else:
+           raise ValueError, 'relation: ' + relation
+
+    def __str__(self):
+       return '%s (%s %s)' % (self.name, self.relationstring, self.version)
+
+    def __repr__(self):
+       return 'VersionedRelation(' + `self.name` + ', ' + \
+               `self.relationstring` + ', ' + `self.version` + ')'
+
+    # version can be the special values Virtual or Any, in addition
+    # to a normal Version instance.
+    def satisfied(self, packagename, version):
+       if packagename != self.name or version is Virtual:
+           return 0
+        if version is Any:
+           return 1
+       return self.relation(version, self.version)
+
+    def satisfied_by(self, packages):
+       version = packages.get(self.name)
+       if version is not None and self.satisfied(self.name, version):
+           return self.name
+       return None
+
+    def packagenames(self):
+       return [self.name]
+
+# Relations joined with the "alternatives" operator, i.e. foo | bar.
+# This class just stores the joined relations as a sequence.
+class AltRelation:
+    def __init__(self, relationlist):
+       self.relations = relationlist
+
+    def __str__(self):
+       return string.join(map(str, self.relations), ' | ')
+
+    def __repr__(self):
+       return 'AltRelation(' + `self.relations` + ')'
+
+    def satisfied(self, packagename, version):
+       for rel in self.relations:
+           if rel.satisfied(packagename, version):
+               return 1
+       return 0
+
+    def satisfied_by(self, packages):
+       rv = []
+       for rel in self.relations:
+           sb = rel.satisfied_by(packages)
+           if sb is not None and rv.count(sb) == 0:
+               rv.append(sb)
+       if len(rv) > 0:
+           return rv
+       return None
+
+    def packagenames(self):
+       return reduce(lambda x, y: x + y.packagenames(), self.relations, [])
+
+def parsealt(str):
+    i = string.find(str, '(')
+    if i == -1:
+       return SimpleRelation(string.strip(str))
+    packagename = string.strip(str[:i])
+    j = string.find(str, ')')
+    relver = string.strip(str[i+1:j])
+    if relver[1] == '<' or relver[1] == '=' or relver[1] == '>':
+       return VersionedRelation(packagename, relver[:2],
+                                version.make(string.strip(relver[2:])))
+    else:
+       return VersionedRelation(packagename, relver[:1],
+                                version.make(string.strip(relver[1:])))
+
+def parse(str):
+    alts = map(parsealt, string.split(str, '|'))
+    if len(alts) > 1:
+       return AltRelation(alts)
+    return alts[0]
+
+# Possible values for the relation attribute
+def strictless(x, y):
+    return x < y
+
+def lessthan(x, y):
+    return x <= y
+
+def equalversion(x, y):
+    return x.equals(y)
+
+def greaterthan(x, y):
+    return x >= y
+
+def strictgreater(x, y):
+    return x > y 
+