]> git.ipfire.org Git - pakfire.git/commitdiff
Add support for requires like "gcc>=4.0.0-1".
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 20 Feb 2011 12:44:19 +0000 (13:44 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 20 Feb 2011 12:44:19 +0000 (13:44 +0100)
pakfire/depsolve.py
pakfire/packages/base.py
pakfire/packages/util.py

index 8808922972252ff22257157f0d33b11b088c8f68..ae7393447d9f367d3ba957d4c3e88d1a4a0ea73b 100644 (file)
@@ -27,6 +27,9 @@ class Requires(object):
                if self.requires.startswith("/"):
                        return "file"
 
+               elif ">" in self.requires or "<" in self.requires or "=" in self.requires:
+                       return "expr"
+
                elif not re.match("^lib.*\.so.*", self.requires):
                        return "lib"
 
index 0019d6bd2fca7411c52f24353ef6fc1d7f29e681..60abf9d2b1ddb55c40b649b7092ca7daf73ca528 100644 (file)
@@ -23,8 +23,7 @@ class Package(object):
                if not self.name == other.name:
                        return cmp(self.name, other.name)
 
-               ret = util.version_compare((self.epoch, self.version, self.release),
-                       (other.epoch, other.version, other.release))
+               ret = util.version_compare(self.version_tuple, other.version_tuple)
 
                # Compare the build times if we have a rebuilt package.
                if not ret:
@@ -155,6 +154,14 @@ class Package(object):
 
                return int(epoch)
 
+       @property
+       def version_tuple(self):
+               """
+                       Returns a tuple like (epoch, version, release) that can
+                       be used to compare versions of packages.
+               """
+               return (self.epoch, self.version, self.release)
+
        @property
        def arch(self):
                raise NotImplementedError
@@ -227,17 +234,39 @@ class Package(object):
                if self.name == requires.requires:
                        return True
 
+               # Get all provide strings from the package data
+               # and return true if requires is matched.
+               if requires.requires in self.provides:
+                       return True
+
                if requires.type == "file":
                        return requires.requires in self.filelist
 
-               # Get all provide strings from the package data
-               # and return true if requires is matched. Otherwise return false.
-               provides = self.provides
+               elif requires.type == "expr":
+                       # Handle all expressions like "gcc>=4.0.0-1"
+                       (e_expr, e_name, e_epoch, e_version, e_release) = \
+                               util.parse_pkg_expr(requires.requires)
+
+                       # If the package names do not match, we do not provide this:
+                       if not self.name == e_name:
+                               return False
+
+                       ret = util.version_compare(self.version_tuple, (e_epoch, e_version, e_release))
+
+                       # If we equal the version, we provide this
+                       if "=" in e_expr and ret == 0:
+                               return True
+
+                       elif ">" in e_expr and ret > 0:
+                               return True
+
+                       elif "<" in e_expr and ret < 0:
+                               return True
+
+                       return False
 
-               return requires.requires in provides
-               
-               # XXX this function has to do lots more of magic:
-               #  e.g. filename matches, etc.
+               # No match was found at all
+               return False
 
        def extract(self, path):
                raise NotImplementedError
index 45d7330af02b3a5733d23095fb003bbc3a8b438d..071dbdd7907566fc2e4f6b170d4a550eb5ef6031 100644 (file)
@@ -3,20 +3,34 @@
 from __future__ import division
 
 import hashlib
+import re
 
 from pakfire.constants import *
 
 def version_compare_epoch(e1, e2):
+       # If either e1 or e2 is None, we cannot say anything
+       if None in (e1, e2):
+               return 0
+
        return cmp(e1, e2)
 
 def version_compare_version(v1, v2):
        return cmp(v1, v2)
 
 def version_compare_release(r1, r2):
+       # If either e1 or e2 is None, we cannot say anything
+       if None in (r1, r2):
+               return 0
+
+       if "." in r1:
+               r1 = r1.split(".")[0]
+
+       if "." in r2:
+               r2 = r2.split(".")[0]
+
        return cmp(r1, r2)
 
 def version_compare((e1, v1, r1), (e2, v2, r2)):
-
        ret = version_compare_epoch(e1, e2)
        if not ret == 0:
                return ret
@@ -65,3 +79,48 @@ def calc_hash1(filename):
 
        f.close()
        return h.hexdigest()
+
+def parse_pkg_expr(s):
+       # Possible formats:
+       #   gcc=4.0.0
+       #   gcc=4.0.0-1
+       #   gcc=4.0.0-1.ip3
+       #   gcc=0:4.0.0-1
+       #   gcc=0:4.0.0-1.ip3
+       #   gcc>=...
+       #   gcc>...
+       #   gcc<...
+       #   gcc<=...
+
+       (name, exp, epoch, version, release) = (None, None, None, None, None)
+
+       m = re.match(r"([A-Za-z0-9\-\+]+)(=|\<|\>|\>=|\<=)([0-9]+\:)?([0-9A-Za-z\.]+)-?([0-9]+\.?[a-z0-9]+|[0-9]+)?", s)
+
+       if m:
+               (name, exp, epoch, version, release) = m.groups()
+
+               # Remove : from epoch and convert to int
+               if epoch:
+                       epoch = epoch.replace(":", "")
+                       epoch = int(epoch)
+
+       return (exp, name, epoch, version, release)
+
+def test_parse_pkg_expr():
+       strings = (
+               "gcc=4.0.0",
+               "gcc=4.0.0-1",
+               "gcc=4.0.0-1.ip3",
+               "gcc=0:4.0.0-1",
+               "gcc=0:4.0.0-1.ip3",
+               "gcc>=4.0.0-1",
+               "gcc>4.0.0-1",
+               "gcc<4.0.0-1",
+               "gcc<=4.0.0-1",
+       )
+
+       for s in strings:
+               print s, parse_pkg_expr(s)
+
+if __name__ == "__main__":
+       test_parse_pkg_expr()