-
-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathrpm.py
More file actions
97 lines (82 loc) · 3.16 KB
/
Copy pathrpm.py
File metadata and controls
97 lines (82 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#
# Copyright (c) SAS Institute Inc.
# SPDX-License-Identifier: Apache-2.0
# Version comparison utility extracted from python-rpm-vercmp and further
# stripped down and significantly modified from the original at python-rpm-vercmp
#
# Visit https://aboutcode.org and https://github.com/nexB/univers for support and download.
import re
class Vercmp:
R_NONALNUMTILDE = re.compile(br"^([^a-zA-Z0-9~]*)(.*)$")
R_NUM = re.compile(br"^([\d]+)(.*)$")
R_ALPHA = re.compile(br"^([a-zA-Z]+)(.*)$")
@classmethod
def compare(cls, first, second):
first = first.encode("ascii", "ignore")
second = second.encode("ascii", "ignore")
while first or second:
m1 = cls.R_NONALNUMTILDE.match(first)
m2 = cls.R_NONALNUMTILDE.match(second)
m1_head, first = m1.group(1), m1.group(2)
m2_head, second = m2.group(1), m2.group(2)
if m1_head or m2_head:
# Ignore junk at the beginning
continue
# handle the tilde separator, it sorts before everything else
if first.startswith(b"~"):
if not second.startswith(b"~"):
return -1
first, second = first[1:], second[1:]
continue
if second.startswith(b"~"):
return 1
# If we ran to the end of either, we are finished with the loop
if not first or not second:
break
# grab first completely alpha or completely numeric segment
m1 = cls.R_NUM.match(first)
if m1:
m2 = cls.R_NUM.match(second)
if not m2:
# numeric segments are always newer than alpha segments
return 1
isnum = True
else:
m1 = cls.R_ALPHA.match(first)
m2 = cls.R_ALPHA.match(second)
isnum = False
if not m1:
# this cannot happen, as we previously tested to make sure that
# the first string has a non-null segment
return -1 # arbitrary
if not m2:
return 1 if isnum else -1
m1_head, first = m1.group(1), m1.group(2)
m2_head, second = m2.group(1), m2.group(2)
if isnum:
# throw away any leading zeros - it's a number, right?
m1_head = m1_head.lstrip(b"0")
m2_head = m2_head.lstrip(b"0")
# whichever number has more digits wins
m1hlen = len(m1_head)
m2hlen = len(m2_head)
if m1hlen < m2hlen:
return -1
if m1hlen > m2hlen:
return 1
# Same number of chars
if m1_head < m2_head:
return -1
if m1_head > m2_head:
return 1
# Both segments equal
continue
m1len = len(first)
m2len = len(second)
if m1len == m2len == 0:
return 0
if m1len != 0:
return 1
return -1
def vercmp(first, second):
return Vercmp.compare(first, second)