summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Mauch <genone@gentoo.org>2005-11-13 16:07:28 +0000
committerMarius Mauch <genone@gentoo.org>2005-11-13 16:07:28 +0000
commit9f3a46665c40b48206c90fabc5befaaeff6b43d0 (patch)
treea38156cbc22ffed23d28baca9eff7625e2f3e611 /pym/portage_versions.py
parentminor glitch: EBUILD_PHASES is a list, no need to split() it (diff)
downloadportage-multirepo-9f3a46665c40b48206c90fabc5befaaeff6b43d0.tar.gz
portage-multirepo-9f3a46665c40b48206c90fabc5befaaeff6b43d0.tar.bz2
portage-multirepo-9f3a46665c40b48206c90fabc5befaaeff6b43d0.zip
Backport of version code rewrite (bug 37406), should be completely backwards compatible (and the algorithm has been tested on the whole tree multiple times already).
Also adds some new features in version syntax like cvs version prefixes (in the same package) and multiple suffixes. svn path=/main/trunk/; revision=2309
Diffstat (limited to 'pym/portage_versions.py')
-rw-r--r--pym/portage_versions.py222
1 files changed, 222 insertions, 0 deletions
diff --git a/pym/portage_versions.py b/pym/portage_versions.py
new file mode 100644
index 00000000..ddb35a38
--- /dev/null
+++ b/pym/portage_versions.py
@@ -0,0 +1,222 @@
+import re,string
+
+ver_regexp = re.compile("^(cvs\\.)?(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?$")
+suffix_regexp = re.compile("^(alpha|beta|rc|pre|p)(\\d*)$")
+suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3, "rc": -1}
+
+def ververify(myver, silent=1):
+ if ver_regexp.match(myver):
+ return 1
+ else:
+ if not silent:
+ print "!!! syntax error in version: %s" % myver
+ return 0
+
+vercmp_cache = {}
+def vercmp(ver1, ver2, silent=1):
+ if ver1 == ver2:
+ return 0
+ mykey=ver1+":"+ver2
+ try:
+ return vercmp_cache[mykey]
+ except KeyError:
+ pass
+ match1 = ver_regexp.match(ver1)
+ match2 = ver_regexp.match(ver2)
+
+ # checking that the versions are valid
+ if not match1 or not match1.groups():
+ if not silent:
+ print "!!! syntax error in version: %s" % ver1
+ return None
+ if not match2 or not match2.groups():
+ if not silent:
+ print "!!! syntax error in version: %s" % ver2
+ return None
+
+ # shortcut for cvs ebuilds (new style)
+ if match1.group(1) and not match2.group(1):
+ vercmp_cache[mykey] = 1
+ return 1
+ elif match2.group(1) and not match1.group(1):
+ vercmp_cache[mykey] = -1
+ return -1
+
+ # building lists of the version parts before the suffix
+ # first part is simple
+ list1 = [string.atoi(match1.group(2))]
+ list2 = [string.atoi(match2.group(2))]
+
+ # this part would greatly benefit from a fixed-length version pattern
+ if len(match1.group(3)) or len(match2.group(3)):
+ vlist1 = match1.group(3)[1:].split(".")
+ vlist2 = match2.group(3)[1:].split(".")
+ for i in range(0, max(len(vlist1), len(vlist2))):
+ if len(vlist1) <= i or len(vlist1[i]) == 0:
+ list1.append(0)
+ list2.append(string.atoi(vlist2[i]))
+ elif len(vlist2) <= i or len(vlist2[i]) == 0:
+ list1.append(string.atoi(vlist1[i]))
+ list2.append(0)
+ # Let's make life easy and use integers unless we're forced to use floats
+ elif (vlist1[i][0] != "0" and vlist2[i][0] != "0"):
+ list1.append(string.atoi(vlist1[i]))
+ list2.append(string.atoi(vlist2[i]))
+ # now we have to use floats so 1.02 compares correctly against 1.1
+ else:
+ list1.append(string.atof("0."+vlist1[i]))
+ list2.append(string.atof("0."+vlist2[i]))
+
+ # and now the final letter
+ if len(match1.group(5)):
+ list1.append(ord(match1.group(5)))
+ if len(match2.group(5)):
+ list2.append(ord(match2.group(5)))
+
+ for i in range(0, max(len(list1), len(list2))):
+ if len(list1) <= i:
+ vercmp_cache[mykey] = -1
+ return -1
+ elif len(list2) <= i:
+ vercmp_cache[mykey] = 1
+ return 1
+ elif list1[i] != list2[i]:
+ vercmp_cache[mykey] = list1[i] - list2[i]
+ return list1[i] - list2[i]
+
+ # main version is equal, so now compare the _suffix part
+ list1 = match1.group(6).split("_")[1:]
+ list2 = match2.group(6).split("_")[1:]
+
+ for i in range(0, max(len(list1), len(list2))):
+ if len(list1) <= i:
+ s1 = ("p","0")
+ else:
+ s1 = suffix_regexp.match(list1[i]).groups()
+ if len(list2) <= i:
+ s2 = ("p","0")
+ else:
+ s2 = suffix_regexp.match(list2[i]).groups()
+ if s1[0] != s2[0]:
+ return suffix_value[s1[0]] - suffix_value[s2[0]]
+ if s1[1] != s2[1]:
+ # it's possible that the s(1|2)[1] == ''
+ # in such a case, fudge it.
+ try: r1 = string.atoi(s1[1])
+ except ValueError: r1 = 0
+ try: r2 = string.atoi(s2[1])
+ except ValueError: r2 = 0
+ return r1 - r2
+
+ # the suffix part is equal to, so finally check the revision
+ if match1.group(10):
+ r1 = string.atoi(match1.group(10))
+ else:
+ r1 = 0
+ if match2.group(10):
+ r2 = string.atoi(match2.group(10))
+ else:
+ r2 = 0
+ vercmp_cache[mykey] = r1 - r2
+ return r1 - r2
+
+def pkgcmp(pkg1, pkg2):
+ if pkg1[0] != pkg2[0]:
+ return None
+ mycmp=vercmp(pkg1[1],pkg2[1])
+ if mycmp>0:
+ return 1
+ if mycmp<0:
+ return -1
+ r1=string.atof(pkg1[2][1:])
+ r2=string.atof(pkg2[2][1:])
+ if r1>r2:
+ return 1
+ if r2>r1:
+ return -1
+ return 0
+
+
+pkgcache={}
+
+def pkgsplit(mypkg,silent=1):
+ try:
+ if not pkgcache[mypkg]:
+ return None
+ return pkgcache[mypkg][:]
+ except KeyError:
+ pass
+ myparts=string.split(mypkg,'-')
+
+ if len(myparts)<2:
+ if not silent:
+ print "!!! Name error in",mypkg+": missing a version or name part."
+ pkgcache[mypkg]=None
+ return None
+ for x in myparts:
+ if len(x)==0:
+ if not silent:
+ print "!!! Name error in",mypkg+": empty \"-\" part."
+ pkgcache[mypkg]=None
+ return None
+
+ #verify rev
+ revok=0
+ myrev=myparts[-1]
+ if len(myrev) and myrev[0]=="r":
+ try:
+ string.atoi(myrev[1:])
+ revok=1
+ except:
+ pass
+ if revok:
+ verPos = -2
+ revision = myparts[-1]
+ else:
+ verPos = -1
+ revision = "r0"
+
+ if ververify(myparts[verPos]):
+ if len(myparts)== (-1*verPos):
+ pkgcache[mypkg]=None
+ return None
+ else:
+ for x in myparts[:verPos]:
+ if ververify(x):
+ pkgcache[mypkg]=None
+ return None
+ #names can't have versiony looking parts
+ myval=[string.join(myparts[:verPos],"-"),myparts[verPos],revision]
+ pkgcache[mypkg]=myval
+ return myval
+ else:
+ pkgcache[mypkg]=None
+ return None
+
+catcache={}
+def catpkgsplit(mydata,silent=1):
+ "returns [cat, pkgname, version, rev ]"
+ try:
+ if not catcache[mydata]:
+ return None
+ return catcache[mydata][:]
+ except KeyError:
+ pass
+ mysplit=mydata.split("/")
+ p_split=None
+ if len(mysplit)==1:
+ retval=["null"]
+ p_split=pkgsplit(mydata,silent=silent)
+ elif len(mysplit)==2:
+ retval=[mysplit[0]]
+ p_split=pkgsplit(mysplit[1],silent=silent)
+ if not p_split:
+ catcache[mydata]=None
+ return None
+ retval.extend(p_split)
+ catcache[mydata]=retval
+ return retval
+
+def catsplit(mydep):
+ return mydep.split("/", 1)
+