26
# XXX: Update as needed
27
# This should really be included in apt-cache policy output... it is already
28
# in the Release file...
29
RELEASE_CODENAME_LOOKUP = {
42
TESTING_CODENAME = 'lenny'
44
def lookup_codename(release, unknown=None):
45
m = re.match(r'(\d+)\.(\d+)(r(\d+))?', release)
49
shortrelease = '%s.%s' % m.group(1,2)
50
return RELEASE_CODENAME_LOOKUP.get(shortrelease, unknown)
52
# LSB compliance packages... may grow eventually
53
PACKAGES = 'lsb-core lsb-cxx lsb-graphics lsb-desktop lsb-qt4 lsb-languages lsb-multimedia lsb-printing'
55
modnamere = re.compile(r'lsb-(?P<module>[a-z0-9]+)-(?P<arch>[^ ]+)(?: \(= (?P<version>[0-9.]+)\))?')
57
def valid_lsb_versions(version, module):
58
# If a module is ever released that only appears in >= version, deal
62
elif version == '3.1':
63
if module in ('desktop', 'qt4'):
66
return ['2.0', '3.0', '3.1']
67
elif version == '3.2':
68
if module == 'desktop':
72
elif module in ('printing', 'languages', 'multimedia'):
75
return ['3.0', '3.1', '3.2']
77
return ['2.0', '3.0', '3.1', '3.2']
82
set # introduced in 2.4
87
# This is Debian-specific at present
88
def check_modules_installed():
89
# Find which LSB modules are installed on this system
90
output = commands.getoutput("dpkg-query -f '${Version} ${Provides}\n' -W %s 2>/dev/null" % PACKAGES)
95
for line in output.split(os.linesep):
96
version, provides = line.split(' ', 1)
97
version = version.split('-', 1)[0]
98
for pkg in provides.split(','):
99
mob = modnamere.search(pkg)
103
mgroups = mob.groupdict()
104
# If no versioned provides...
105
if mgroups.get('version'):
106
module = '%(module)s-%(version)s-%(arch)s' % mgroups
109
module = mgroups['module']
110
for v in valid_lsb_versions(version, module):
111
mgroups['version'] = v
112
module = '%(module)s-%(version)s-%(arch)s' % mgroups
115
modules = list(modules)
119
longnames = {'v' : 'version', 'o': 'origin', 'a': 'suite',
120
'c' : 'component', 'l': 'label'}
122
def parse_policy_line(data):
124
bits = data.split(',')
126
kv = bit.split('=', 1)
130
retval[longnames[k]] = v
133
def parse_apt_policy():
136
policy = commands.getoutput('apt-cache policy 2>/dev/null')
137
for line in policy.split('\n'):
139
m = re.match(r'(\d+)', line)
141
priority = int(m.group(1))
142
if line.startswith('release'):
143
bits = line.split(' ', 1)
145
data.append( (priority, parse_policy_line(bits[1])) )
149
def guess_release_from_apt(origin='Debian', component='main',
150
ignoresuites=('experimental'),
152
releases = parse_apt_policy()
157
# We only care about the specified origin, component, and label
158
releases = [x for x in releases if (
159
x[1].get('origin', '') == origin and
160
x[1].get('component', '') == component and
161
x[1].get('label', '') == label)]
163
# Check again to make sure we didn't wipe out all of the releases
170
# We've sorted the list by descending priority, so the first entry should
171
# be the "main" release in use on the system
173
return releases[0][1]
175
def guess_debian_release():
176
distinfo = {'ID' : 'Debian'}
179
if kern in ('Linux', 'Hurd', 'NetBSD'):
180
distinfo['OS'] = 'GNU/'+kern
181
elif kern == 'FreeBSD':
182
distinfo['OS'] = 'GNU/k'+kern
184
distinfo['OS'] = 'GNU'
186
distinfo['DESCRIPTION'] = '%(ID)s %(OS)s' % distinfo
188
if os.path.exists('/etc/debian_version'):
189
release = open('/etc/debian_version').read().strip()
190
if not release[0:1].isalpha():
191
# /etc/debian_version should be numeric
192
codename = lookup_codename(release, 'n/a')
193
distinfo.update({ 'RELEASE' : release, 'CODENAME' : codename })
194
elif release.endswith('/sid'):
195
distinfo['RELEASE'] = 'testing/unstable'
197
distinfo['RELEASE'] = release
199
# Only use apt information if we did not get the proper information
200
# from /etc/debian_version or if we don't have a codename
201
# (which will happen if /etc/debian_version does not contain a
202
# number but some text like 'testing/unstable' or 'lenny/sid')
204
# This is slightly faster and less error prone in case the user
205
# has an entry in his /etc/apt/sources.list but has not actually
206
# upgraded the system.
207
rinfo = guess_release_from_apt()
208
if rinfo and not distinfo.get('CODENAME'):
209
release = rinfo.get('version')
211
codename = lookup_codename(release, 'n/a')
213
release = rinfo.get('suite', 'unstable')
214
if release == 'testing':
215
# Would be nice if I didn't have to hardcode this.
216
codename = TESTING_CODENAME
219
distinfo.update({ 'RELEASE' : release, 'CODENAME' : codename })
221
if distinfo.get('RELEASE'):
222
distinfo['DESCRIPTION'] += ' %(RELEASE)s' % distinfo
223
if distinfo.get('CODENAME'):
224
distinfo['DESCRIPTION'] += ' (%(CODENAME)s)' % distinfo
228
# Whatever is guessed above can be overridden in /etc/lsb-release
229
def get_lsb_information():
231
if os.path.exists('/etc/lsb-release'):
232
for line in open('/etc/lsb-release'):
239
var, arg = line.split('=', 1)
240
if var.startswith('DISTRIB_'):
242
if arg.startswith('"') and arg.endswith('"'):
247
def get_distro_information():
248
lsbinfo = get_lsb_information()
249
# OS is only used inside guess_debian_release anyway
250
for key in ('ID', 'RELEASE', 'CODENAME', 'DESCRIPTION',):
251
if key not in lsbinfo:
252
distinfo = guess_debian_release()
253
distinfo.update(lsbinfo)
259
29
parser = OptionParser()
260
30
parser.add_option('-v', '--version', dest='version', action='store_true',