From: Michael Tremer Date: Sun, 20 Feb 2011 12:44:19 +0000 (+0100) Subject: Add support for requires like "gcc>=4.0.0-1". X-Git-Tag: 0.9.3~155 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=268dd720751f54fc84015a50c317d90c768b3d16;p=pakfire.git Add support for requires like "gcc>=4.0.0-1". --- diff --git a/pakfire/depsolve.py b/pakfire/depsolve.py index 880892297..ae7393447 100644 --- a/pakfire/depsolve.py +++ b/pakfire/depsolve.py @@ -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" diff --git a/pakfire/packages/base.py b/pakfire/packages/base.py index 0019d6bd2..60abf9d2b 100644 --- a/pakfire/packages/base.py +++ b/pakfire/packages/base.py @@ -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 diff --git a/pakfire/packages/util.py b/pakfire/packages/util.py index 45d7330af..071dbdd79 100644 --- a/pakfire/packages/util.py +++ b/pakfire/packages/util.py @@ -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()