summaryrefslogtreecommitdiff
path: root/client/bin/kernel_versions.py
blob: 3af08fe78b21b2cfb3177187663ae7575147712a (plain)
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#
# kernel_versions.py -- linux kernel version comparisons
#
__author__ = """Copyright Andy Whitcroft 2007"""

import sys,re

# 
# Sort key for ordering versions chronologically.  The key ordering
# problem is between that introduced by -rcN.  These come _before_
# their accompanying version.
# 
#   2.6.0 -> 2.6.1-rc1 -> 2.6.1
# 
# In order to sort them we convert all non-rc releases to a pseudo
# -rc99 release.  We also convert all numbers to two digits.  The
# result is then sortable textually.
# 
#   02.06.00-rc99 -> 02.06.01-rc01 -> 02.06.01-rc99
# 
encode_sep = re.compile(r'(\D+)')

def version_encode(version):
	bits = encode_sep.split(version)
	n = 9
	if len(bits[0]) == 0:
		n += 2
	if len(bits) == n or (len(bits) > n and bits[n] != '_rc'):
		# Insert missing _rc99 after 2 . 6 . 18 -smp- 220 . 0 
		bits.insert(n, '_rc')
		bits.insert(n+1, '99')
	n = 5
	if len(bits[0]) == 0:
		n += 2
	if len(bits) <= n or bits[n] != '-rc':
		bits.insert(n, '-rc')
		bits.insert(n+1, '99')
	for n in range(0, len(bits), 2):
		if len(bits[n]) == 1:
			bits[n] = '0' + bits[n]

	return ''.join(bits)


def version_limit(version, n):
	bits = encode_sep.split(version)
	return ''.join(bits[0:n])


def version_len(version):
	return len(encode_sep.split(version))

#
# Given a list of versions find the nearest version which is deemed
# less than or equal to the target.  Versions are in linux order
# as follows:
# 
#   2.6.0 -> 2.6.1 -> 2.6.2-rc1 -> 2.6.2-rc2 -> 2.6.2 -> 2.6.3-rc1
#              |        |\
#              |        | 2.6.2-rc1-mm1 -> 2.6.2-rc1-mm2
#              |        \
#              |         2.6.2-rc1-ac1 -> 2.6.2-rc1-ac2
#              \   
#               2.6.1-mm1 -> 2.6.1-mm2
# 
# Note that a 2.6.1-mm1 is not a predecessor of 2.6.2-rc1-mm1.
#
def version_choose_config(version, candidates):
	# Check if we have an exact match ... if so magic
	if version in candidates:
		return version

	# Sort the search key into the list ordered by 'age'
	deco = [ (version_encode(v), i, v) for i, v in
					enumerate(candidates + [ version ]) ]
	deco.sort()
	versions = [ v for _, _, v in deco ]

	# Everything sorted below us is of interst.
	for n in range(len(versions) - 1, -1, -1):
		if versions[n] == version:
			break
	n -= 1

	# Try ever shorter 'prefixes' 2.6.20-rc3-mm, 2.6.20-rc, 2.6. etc
	# to match against the ordered list newest to oldest.
	length = version_len(version) - 1
	version = version_limit(version, length)
	while length > 1:
		for o in range(n, -1, -1):
			if version_len(versions[o]) == (length + 1) and \
			   version_limit(versions[o], length) == version:
				return versions[o]
		length -= 2
		version = version_limit(version, length)

	return None


def is_released_kernel(version):
	# True if version name suggests a released kernel,  
	#   not some release candidate or experimental kernel name
	#   e.g.  2.6.18-smp-200.0  includes no other text, underscores, etc
	version = version.strip('01234567890.-')
	return version in ['', 'smp', 'smpx', 'pae']


def is_release_candidate(version):
	# True if version names a released kernel or release candidate,
	#   not some experimental name containing arbitrary text
	#   e.g.  2.6.18-smp-220.0_rc3  but not  2.6.18_patched
	version = re.sub(r'[_-]rc\d+', '', version)
	return is_released_kernel(version)