~ubuntu-branches/ubuntu/quantal/lsb/quantal-proposed

« back to all changes in this revision

Viewing changes to lsb_release

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek, Jeff Licquia
  • Date: 2009-06-02 20:20:07 UTC
  • mfrom: (1.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090602202007-yrfljcu970v0kcqd
Tags: 4.0-0ubuntu1
* Merge from Debian unstable, remaining changes:
  - lsb-base-logging-ubuntu.sh: change log_{success,warning,failure}_msg()
    to use usplash_write "TEXT" instead of "STATUS" to avoid unreadable
    line-wrapping when using usplash in verbose mode.
  - Don't conflict with python (>= 2.6).
  - Depend on postfix rather than exim4 as preferred mail-transport-agent
    alternative.
  - Depend on libgl1-mesa-glx rather than libgl1-mesa as preferred libgl1
    alternative.
  - Since /etc/lsb-release overrides detected information, there's no
    need to try and detect that information if lsb-release contains
    everything we need.  This saves us calling the hugely expensive
    apt-cache.
  - Add Ubuntu logging functions.

[ Jeff Licquia ]
* Upgrade to support LSB 4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import os
24
24
import re
25
25
 
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 = {
30
 
    '1.1' : 'buzz',
31
 
    '1.2' : 'rex',
32
 
    '1.3' : 'bo',
33
 
    '2.0' : 'hamm',
34
 
    '2.1' : 'slink',
35
 
    '2.2' : 'potato',
36
 
    '3.0' : 'woody',
37
 
    '3.1' : 'sarge',
38
 
    '4.0' : 'etch',
39
 
    '5.0' : 'lenny',
40
 
    }
41
 
 
42
 
TESTING_CODENAME = 'lenny'
43
 
 
44
 
def lookup_codename(release, unknown=None):
45
 
    m = re.match(r'(\d+)\.(\d+)(r(\d+))?', release)
46
 
    if not m:
47
 
        return unknown
48
 
 
49
 
    shortrelease = '%s.%s' % m.group(1,2)
50
 
    return RELEASE_CODENAME_LOOKUP.get(shortrelease, unknown)
51
 
 
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'
54
 
 
55
 
modnamere = re.compile(r'lsb-(?P<module>[a-z0-9]+)-(?P<arch>[^ ]+)(?: \(= (?P<version>[0-9.]+)\))?')
56
 
 
57
 
def valid_lsb_versions(version, module):
58
 
    # If a module is ever released that only appears in >= version, deal
59
 
    # with that here
60
 
    if version == '3.0':
61
 
        return ['2.0', '3.0']
62
 
    elif version == '3.1':
63
 
        if module in ('desktop', 'qt4'):
64
 
            return ['3.1']
65
 
        else:
66
 
            return ['2.0', '3.0', '3.1']
67
 
    elif version == '3.2':
68
 
        if module == 'desktop':
69
 
            return ['3.1', '3.2']
70
 
        elif module == 'qt4':
71
 
            return ['3.1']
72
 
        elif module in ('printing', 'languages', 'multimedia'):
73
 
            return ['3.2']
74
 
        elif module == 'cxx':
75
 
            return ['3.0', '3.1', '3.2']
76
 
        else:
77
 
            return ['2.0', '3.0', '3.1', '3.2']
78
 
 
79
 
    return [version]
80
 
 
81
 
try:
82
 
    set # introduced in 2.4
83
 
except NameError:
84
 
    import sets
85
 
    set = sets.Set
86
 
 
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)
91
 
    if not output:
92
 
        return []
93
 
 
94
 
    modules = set()
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)
100
 
            if not mob:
101
 
                continue
102
 
 
103
 
            mgroups = mob.groupdict()
104
 
            # If no versioned provides...
105
 
            if mgroups.get('version'):
106
 
                module = '%(module)s-%(version)s-%(arch)s' % mgroups
107
 
                modules.add(module)
108
 
            else:
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
113
 
                    modules.add(module)
114
 
 
115
 
    modules = list(modules)
116
 
    modules.sort()
117
 
    return modules
118
 
 
119
 
longnames = {'v' : 'version', 'o': 'origin', 'a': 'suite',
120
 
             'c' : 'component', 'l': 'label'}
121
 
 
122
 
def parse_policy_line(data):
123
 
    retval = {}
124
 
    bits = data.split(',')
125
 
    for bit in bits:
126
 
        kv = bit.split('=', 1)
127
 
        if len(kv) > 1:
128
 
            k, v = kv[:2]
129
 
            if k in longnames:
130
 
                retval[longnames[k]] = v
131
 
    return retval
132
 
 
133
 
def parse_apt_policy():
134
 
    data = []
135
 
    
136
 
    policy = commands.getoutput('apt-cache policy 2>/dev/null')
137
 
    for line in policy.split('\n'):
138
 
        line = line.strip()
139
 
        m = re.match(r'(\d+)', line)
140
 
        if m:
141
 
            priority = int(m.group(1))
142
 
        if line.startswith('release'):
143
 
            bits = line.split(' ', 1)
144
 
            if len(bits) > 1:
145
 
                data.append( (priority, parse_policy_line(bits[1])) )
146
 
 
147
 
    return data
148
 
 
149
 
def guess_release_from_apt(origin='Debian', component='main',
150
 
                           ignoresuites=('experimental'),
151
 
                           label='Debian'):
152
 
    releases = parse_apt_policy()
153
 
 
154
 
    if not releases:
155
 
        return None
156
 
 
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)]
162
 
 
163
 
    # Check again to make sure we didn't wipe out all of the releases
164
 
    if not releases:
165
 
        return None
166
 
    
167
 
    releases.sort()
168
 
    releases.reverse()
169
 
 
170
 
    # We've sorted the list by descending priority, so the first entry should
171
 
    # be the "main" release in use on the system
172
 
 
173
 
    return releases[0][1]
174
 
 
175
 
def guess_debian_release():
176
 
    distinfo = {'ID' : 'Debian'}
177
 
 
178
 
    kern = os.uname()[0]
179
 
    if kern in ('Linux', 'Hurd', 'NetBSD'):
180
 
        distinfo['OS'] = 'GNU/'+kern
181
 
    elif kern == 'FreeBSD':
182
 
        distinfo['OS'] = 'GNU/k'+kern
183
 
    else:
184
 
        distinfo['OS'] = 'GNU'
185
 
 
186
 
    distinfo['DESCRIPTION'] = '%(ID)s %(OS)s' % distinfo
187
 
 
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'
196
 
        else:
197
 
            distinfo['RELEASE'] = release
198
 
 
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')
203
 
    #
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')
210
 
        if release:
211
 
            codename = lookup_codename(release, 'n/a')
212
 
        else:
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
217
 
            else:
218
 
                codename = 'sid'
219
 
        distinfo.update({ 'RELEASE' : release, 'CODENAME' : codename })
220
 
 
221
 
    if distinfo.get('RELEASE'):
222
 
        distinfo['DESCRIPTION'] += ' %(RELEASE)s' % distinfo
223
 
    if distinfo.get('CODENAME'):
224
 
        distinfo['DESCRIPTION'] += ' (%(CODENAME)s)' % distinfo
225
 
 
226
 
    return distinfo
227
 
 
228
 
# Whatever is guessed above can be overridden in /etc/lsb-release
229
 
def get_lsb_information():
230
 
    distinfo = {}
231
 
    if os.path.exists('/etc/lsb-release'):
232
 
        for line in open('/etc/lsb-release'):
233
 
            line = line.strip()
234
 
            if not line:
235
 
                continue
236
 
            # Skip invalid lines
237
 
            if not '=' in line:
238
 
                continue
239
 
            var, arg = line.split('=', 1)
240
 
            if var.startswith('DISTRIB_'):
241
 
                var = var[8:]
242
 
                if arg.startswith('"') and arg.endswith('"'):
243
 
                    arg = arg[1:-1]
244
 
                distinfo[var] = arg
245
 
    return distinfo
246
 
 
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)
254
 
            return distinfo
255
 
    else:
256
 
        return lsbinfo
257
 
    
 
26
import lsb_release
 
27
 
258
28
def main():
259
29
    parser = OptionParser()
260
30
    parser.add_option('-v', '--version', dest='version', action='store_true',
284
54
        parser.error("No arguments are permitted")
285
55
 
286
56
    short = (options.short)
287
 
    all = (options.all)
288
57
    none = not (options.all or options.version or options.id or
289
58
                options.description or options.codename or options.release)
290
59
 
291
 
    distinfo = get_distro_information()
 
60
    distinfo = lsb_release.get_distro_information()
292
61
 
293
 
    if none or all or options.version:
294
 
        verinfo = check_modules_installed()
 
62
    if none or options.all or options.version:
 
63
        verinfo = lsb_release.check_modules_installed()
295
64
        if not verinfo:
296
65
            print >> sys.stderr, "No LSB modules are available."
297
66
        elif short:
299
68
        else:
300
69
            print 'LSB Version:\t' + ':'.join(verinfo)
301
70
 
302
 
    if options.id or all:
 
71
    if options.id or options.all:
303
72
        if short:
304
73
            print distinfo.get('ID', 'n/a')
305
74
        else:
306
75
            print 'Distributor ID:\t%s' % distinfo.get('ID', 'n/a')
307
76
 
308
 
    if options.description or all:
 
77
    if options.description or options.all:
309
78
        if short:
310
79
            print distinfo.get('DESCRIPTION', 'n/a')
311
80
        else:
312
81
            print 'Description:\t%s' % distinfo.get('DESCRIPTION', 'n/a')
313
82
 
314
 
    if options.release or all:
 
83
    if options.release or options.all:
315
84
        if short:
316
85
            print distinfo.get('RELEASE', 'n/a')
317
86
        else:
318
87
            print 'Release:\t%s' % distinfo.get('RELEASE', 'n/a')
319
88
 
320
 
    if options.codename or all:
 
89
    if options.codename or options.all:
321
90
        if short:
322
91
            print distinfo.get('CODENAME', 'n/a')
323
92
        else: