#!/usr/bin/python # -*- coding: utf-8 -*- import re import rpm RPMSENSE_LESS = 0x02 RPMSENSE_GREATER = 0x04 RPMSENSE_EQUAL = 0x08 RPMSENSE_SENSEMASK = 0x0f RPMSENSE_FIND_PROVIDES = 0x8000 RPMSENSE_MISSINGOK = 0x80000 RPMSENSE_SCRIPT_POST = 0x400 RPMSENSE_SCRIPT_PREUN = 0x800 RPMSENSE_SCRIPT_POSTUN = 0x1000 def version_ok(required_version, compare_flag, candidate_version): def sep_version(version): vrem = re.match(r'\A(.+)(\-[^\-\:]+)(\:[^\:]+|)\Z', version) if vrem: return (vrem.group(1), vrem.group(2), vrem.group(3)) return (version, '', '') def simple_version(version): version = re.sub(r'[\-:]', '.', version) version = re.sub(r'[a-z]+', '.', version, flags=re.I) version = re.sub(r'\.\Z', '', version) return version def format_versions(ver1, ver2): #see urpm-repoclosure, formatVersions # v1 - provided # v2 - required (e1, e2) = (None, None) e1_m = re.match(r'\A([^\-\:]+)\:(.*)', ver1) if e1_m: (e1, ver1) = (e1_m.group(1), e1_m.group(2)) e2_m = re.match(r'\A([^\-\:]+)\:(.*)', ver2) if e2_m: (e2, ver2) = (e2_m.group(1), e2_m.group(2)) (ver1_m, ver1_r, ver1_rr) = sep_version(ver1) (ver2_m, ver2_r, ver2_rr) = sep_version(ver2) if not ver2_rr: ver1_rr = '' if not ver2_r: ver1_r = '' ver1 = ver1_m + ver1_r + ver1_rr ver2 = ver2_m + ver2_r + ver2_rr if e1_m and e2_m: ver1 = e1 + '.' + ver1 ver2 = e2 + '.' + ver2 return (simple_version(ver1), simple_version(ver2)) def cmp_nums(num1, num2): # 00503 # 12 if num1 == num2: return 0 lzeros1 = re.match(r'\A([0]+)([1-9].*)', num1) if lzeros1: (num1, num2) = (lzeros1.group(2), num2 + lzeros1.group(1)) lzeros2 = re.match(r'\A([0]+)([1-9].*)', num2) if lzeros2: (num2, num1) = (lzeros2.group(2), num1 + lzeros2.group(1)) diff = int(num1) - int(num2) return 0 if diff == 0 else \ (1 if diff > 0 else -1) def cmp_versions(version1, version2): #see urpm-repoclosure, cmpVersions # 3.2.5-5:2011.0 # NOTE: perl 5.00503 and 5.12 (v1, v2) = format_versions(version1, version2) if v1 == v2: return 0 v1parts = v1.split('.') v2parts = v2.split('.') for i in xrange(0, min(len(v1parts), len(v2parts))): (num1, num2)= (v1parts[i], v2parts[i]) if (len(num1) > 0 and len(num2) == 0): return 1 if (len(num1) == 0 and len(num2) > 0): return -1 num_diff = cmp_nums(num1, num2) if num_diff != 0: return num_diff if len(v1parts) < len(v2parts): return -1 if len(v1parts) > len(v2parts): return 1 return 0 def rpm_cmp_versions(version1, version2): def stringToVersion(verstring): # from rpmUtils if verstring in [None, '']: return (None, None, None) e1_m = re.match(r'\A([^\-\:]+)\:(.*)', verstring) epoch = None if e1_m: (epoch, verstring) = (e1_m.group(1), e1_m.group(2)) j = verstring.find('-') if j != -1: if verstring[:j] == '': version = None else: version = verstring[:j] release = verstring[j + 1:] else: if verstring == '': version = None else: version = verstring release = None return (epoch, version, release) (e1, v1, r1) = stringToVersion(version1) (e2, v2, r2) = stringToVersion(version2) if e1 is None or e2 is None: e1 = '0' e2 = '0' result = rpm.labelCompare((e1, v1, r1), (e2, v2, r2)) return result # print '===', required_version, compare_flag, candidate_version if compare_flag == 0: return True if candidate_version == '*': return True #see urpm-repoclosure, checkDeps if compare_flag == RPMSENSE_EQUAL and \ candidate_version ==required_version: return True cmp_res = cmp_versions(candidate_version, required_version) rpm_cmp_res = rpm_cmp_versions(candidate_version, required_version) #if (cmp_res != rpm_cmp_res): #print >> sys.stderr, ('Invalid compare: "%s" vs "%s"! Results: rc: %d, rpm: %d.' % #(candidate_version, required_version, cmp_res, rpm_cmp_res)) if compare_flag == RPMSENSE_EQUAL: return cmp_res == 0 elif compare_flag == RPMSENSE_LESS | RPMSENSE_EQUAL: return cmp_res <= 0 elif compare_flag == RPMSENSE_GREATER | RPMSENSE_EQUAL: return cmp_res >= 0 elif compare_flag == RPMSENSE_LESS: return cmp_res < 0 elif compare_flag == RPMSENSE_GREATER: return cmp_res > 0 return False