~ubuntu-branches/debian/experimental/dogtail/experimental

« back to all changes in this revision

Viewing changes to .pc/0002-apt_api_update.patch/dogtail/distro.py

  • Committer: Package Import Robot
  • Author(s): Alessio Treglia
  • Date: 2013-02-09 16:01:44 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20130209160144-k2yk35tll4eew9wg
Tags: 0.8.1-1
* New maintainer. (Closes: #696136) (Closes: #553898)
* Set packaging format to 3.0 (quilt).
* New upstream release (Closes: #486452):
  - String exceptions are not used anymore. (Closes: #585287)
  - Fix missing check in findChildren(), tree.py (Closes: #485758)
* ACK NMUs:
  - Convert APT's API patch into the quilt format. (Closes: #572087)
  - Convert Ludovico Gardenghi's patch into the quilt
    format. (Closes: #485752)
* Fix desktop file as Freedesktop.org's per-spec.
* Migrate from CDBS + python-support to DH short-form + dh_python2.
* Move to section python.
* Refresh {,Build-}Depends lists.
* Remove xbase-clients from Depends. (Closes: #601486)
* Add Homepage field. (Closes: #572570)
* Add watch file.
* Add gbp config file.
* Refresh debian/copyright to meet copyright format 1.0.
* Install NEWS as upstream changelog.
* Bump Standards.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Handles differences between different distributions
 
2
 
 
3
Authors: Dave Malcolm <dmalcolm@redhat.com>, Zack Cerza <zcerza@redhat.com>"""
 
4
__author__ = "Dave Malcolm <dmalcolm@redhat.com>, Zack Cerza <zcerza@redhat.com>"
 
5
 
 
6
import os
 
7
import re
 
8
from version import Version
 
9
from logging import debugLogger as logger
 
10
 
 
11
class DistributionNotSupportedError(Exception):
 
12
    """
 
13
    This distribution is not supported.
 
14
    """
 
15
    PATCH_MESSAGE = "Please send patches to dogtail-devel-list@gnome.org"
 
16
 
 
17
    def __init__(self, distro):
 
18
        self.distro = distro
 
19
 
 
20
    def __str__(self):
 
21
        return self.distro + ". " + DistributionNotSupportedError.PATCH_MESSAGE
 
22
 
 
23
class PackageNotFoundError(Exception):
 
24
    """
 
25
    Error finding the requested package.
 
26
    """
 
27
    pass
 
28
 
 
29
global packageDb
 
30
global distro
 
31
 
 
32
class PackageDb:
 
33
    """
 
34
    Class to abstract the details of whatever software package database is in
 
35
    use (RPM, APT, etc)
 
36
    """
 
37
    def __init__(self):
 
38
        self.prefix = '/usr'
 
39
        self.localePrefixes = [self.prefix + '/share/locale']
 
40
 
 
41
    def getVersion(self, packageName):
 
42
        """
 
43
        Method to get the version of an installed package as a Version 
 
44
        instance (or raise an exception if not found)
 
45
        
 
46
        Note: does not know about distributions' internal revision numbers.
 
47
        """
 
48
        raise NotImplementedError
 
49
 
 
50
    def getFiles(self, packageName):
 
51
        """
 
52
        Method to get a list of filenames owned by the package, or raise an 
 
53
        exception if not found.
 
54
        """
 
55
        raise NotImplementedError
 
56
 
 
57
    def getMoFiles(self, locale = None):
 
58
        """
 
59
        Method to get a list of all .mo files on the system, optionally for a
 
60
        specific locale.
 
61
        """
 
62
        moFiles = {}
 
63
 
 
64
        def appendIfMoFile(moFiles, dirName, fNames):
 
65
            import re
 
66
            for fName in fNames:
 
67
                if re.match('(.*)\\.mo', fName):
 
68
                    moFiles[dirName + '/' + fName] = None
 
69
 
 
70
        for localePrefix in self.localePrefixes:
 
71
            if locale: localePrefix = localePrefix + '/' + locale
 
72
            os.path.walk(localePrefix, appendIfMoFile, moFiles)
 
73
 
 
74
        return moFiles.keys()
 
75
 
 
76
    def getDependencies(self, packageName):
 
77
        """
 
78
        Method to get a list of unique package names that this package
 
79
        is dependent on, or raise an exception if the package is not
 
80
        found.
 
81
        """
 
82
        raise NotImplementedError
 
83
 
 
84
class _RpmPackageDb(PackageDb):
 
85
    def __init__(self):
 
86
        PackageDb.__init__(self)
 
87
 
 
88
    def getVersion(self, packageName):
 
89
        import rpm
 
90
        ts = rpm.TransactionSet()
 
91
        for header in ts.dbMatch("name", packageName):
 
92
            return Version.fromString(header["version"])
 
93
        raise PackageNotFoundError, packageName
 
94
 
 
95
    def getFiles(self, packageName):
 
96
        import rpm
 
97
        ts = rpm.TransactionSet()
 
98
        for header in ts.dbMatch("name", packageName):
 
99
            return header["filenames"]
 
100
        raise PackageNotFoundError, packageName
 
101
 
 
102
    def getDependencies(self, packageName):
 
103
        import rpm
 
104
        ts = rpm.TransactionSet()
 
105
        for header in ts.dbMatch("name", packageName):
 
106
            # Simulate a set using a hash (to a dummy value);
 
107
            # sets were only added in Python 2.4
 
108
            result = {}
 
109
 
 
110
            # Get the list of requirements; these are
 
111
            # sometimes package names, but can also be
 
112
            # so-names of libraries, and invented virtual
 
113
            # ids
 
114
            for requirement in header[rpm.RPMTAG_REQUIRES]:
 
115
                # Get the name of the package providing
 
116
                # this requirement:
 
117
                for depPackageHeader in ts.dbMatch("provides", requirement):
 
118
                    depName = depPackageHeader['name']
 
119
                    if depName!=packageName:
 
120
                        # Add to the Hash with a dummy value
 
121
                        result[depName]=None
 
122
            return result.keys()
 
123
        raise PackageNotFoundError, packageName
 
124
 
 
125
class _AptPackageDb(PackageDb):
 
126
    def __init__(self):
 
127
        PackageDb.__init__(self)
 
128
        self.cache = None
 
129
 
 
130
    def getVersion(self, packageName):
 
131
        if not self.cache:
 
132
            import apt_pkg
 
133
            apt_pkg.init()
 
134
            self.cache = apt_pkg.GetCache()
 
135
        packages = self.cache.Packages
 
136
        for package in packages:
 
137
            if package.Name == packageName:
 
138
                import re
 
139
                verString = re.match('.*Ver:\'(.*)-.*\' Section:', str(package.CurrentVer)).group(1)
 
140
                return Version.fromString(verString)
 
141
        raise PackageNotFoundError, packageName
 
142
 
 
143
    def getFiles(self, packageName):
 
144
        files = []
 
145
        list = os.popen('dpkg -L %s' % packageName).readlines()
 
146
        if not list:
 
147
            raise PackageNotFoundError, packageName
 
148
        else:
 
149
            for line in list:
 
150
                file = line.strip()
 
151
                if file: files.append(file)
 
152
            return files
 
153
 
 
154
    def getDependencies(self, packageName):
 
155
        # Simulate a set using a hash (to a dummy value);
 
156
        # sets were only added in Python 2.4
 
157
        result = {}
 
158
        if not self.cache:
 
159
            import apt_pkg
 
160
            apt_pkg.init()
 
161
            self.cache = apt_pkg.GetCache()
 
162
        packages = self.cache.Packages
 
163
        for package in packages:
 
164
            if package.Name == packageName:
 
165
                current = package.CurrentVer
 
166
                if not current:
 
167
                    raise PackageNotFoundError, packageName
 
168
                depends = current.DependsList
 
169
                list = depends['Depends']
 
170
                for dependency in list:
 
171
                    name = dependency[0].TargetPkg.Name
 
172
                    # Add to the hash using a dummy value
 
173
                    result[name] = None
 
174
        return result.keys()
 
175
 
 
176
class _UbuntuAptPackageDb(_AptPackageDb):
 
177
    def __init__(self):
 
178
        _AptPackageDb.__init__(self)
 
179
        self.localePrefixes.append(self.prefix + '/share/locale-langpack')
 
180
 
 
181
class _PortagePackageDb(PackageDb):
 
182
    def __init__(self):
 
183
        PackageDb.__init__(self)
 
184
 
 
185
    def getVersion(self, packageName):
 
186
        # the portage utilities are almost always going to be in 
 
187
        # /usr/lib/portage/pym
 
188
        import sys
 
189
        sys.path.append ('/usr/lib/portage/pym')
 
190
        import portage
 
191
        # FIXME: this takes the first package returned in the list, in the 
 
192
        # case that there are slotted packages, and removes the leading 
 
193
        # category such as 'sys-apps'
 
194
        gentooPackageName = portage.db["/"]["vartree"].dbapi.match(packageName)[0].split('/')[1];
 
195
        # this removes the distribution specific versioning returning only the
 
196
        # upstream version
 
197
        upstreamVersion = portage.pkgsplit(gentooPackageName)[1]
 
198
        #print "Version of package is: " + upstreamVersion
 
199
        return Version.fromString(upstreamVersion);
 
200
 
 
201
class _ConaryPackageDb(PackageDb):
 
202
    def __init__(self):
 
203
        PackageDb.__init__(self)
 
204
 
 
205
    def getVersion(self, packageName):
 
206
        import conary
 
207
        from conaryclient import ConaryClient
 
208
        client = ConaryClient()
 
209
        dbVersions = client.db.getTroveVersionList(packageName)
 
210
        if not len(dbVersions):
 
211
            raise PackageNotFoundError, packageName
 
212
        return dbVersions[0].trailingRevision().asString().split("-")[0]
 
213
 
 
214
# getVersion not implemented because on Solaris multiple modules are installed
 
215
# in single packages, so it is hard to tell what version number of a specific
 
216
# module.
 
217
class _SolarisPackageDb(PackageDb):
 
218
    def __init__(self):
 
219
        PackageDb.__init__(self)
 
220
 
 
221
class JhBuildPackageDb(PackageDb):
 
222
    def __init__(self):
 
223
        PackageDb.__init__(self)
 
224
        prefixes = []
 
225
        prefixes.append(os.environ['LD_LIBRARY_PATH'])
 
226
        prefixes.append(os.environ['XDG_CONFIG_DIRS'])
 
227
        prefixes.append(os.environ['PKG_CONFIG_PATH'])
 
228
        self.prefix = os.path.commonprefix(prefixes)
 
229
        self.localePrefixes.append(self.prefix + '/share/locale')
 
230
 
 
231
    def getDependencies(self, packageName):
 
232
        result = {}
 
233
        lines = os.popen('jhbuild list ' + packageName).readlines()
 
234
        for line in lines:
 
235
            if line:
 
236
                result[line.strip()] = None
 
237
        return result.keys()
 
238
 
 
239
class Distro:
 
240
    """
 
241
    Class representing a distribution.
 
242
 
 
243
    Scripts may want to do arbitrary logic based on whichever distro is in use
 
244
    (e.g. handling differences in names of packages, distribution-specific 
 
245
    patches, etc.)
 
246
 
 
247
    We can either create methods in the Distro class to handle these, or we 
 
248
    can use constructs like isinstance(distro, Ubuntu) to handle this. We can
 
249
    even create hierarchies of distro subclasses to handle this kind of thing
 
250
    (could get messy fast though)
 
251
    """
 
252
 
 
253
class Fedora(Distro):
 
254
    def __init__(self):
 
255
        self.packageDb = _RpmPackageDb()
 
256
 
 
257
class RHEL(Fedora):
 
258
    pass
 
259
 
 
260
class Debian(Distro):
 
261
    def __init__(self):
 
262
        self.packageDb = _AptPackageDb()
 
263
 
 
264
class Ubuntu(Debian):
 
265
    def __init__(self):
 
266
        self.packageDb = _UbuntuAptPackageDb()
 
267
 
 
268
class Suse(Distro):
 
269
    def __init__(self):
 
270
        self.packageDb = _RpmPackageDb()
 
271
 
 
272
class Gentoo(Distro):
 
273
    def __init__(self):
 
274
        self.packageDb = _PortagePackageDb()
 
275
 
 
276
class Conary(Distro):
 
277
    def __init__(self):
 
278
        self.packageDb = _ConaryPackageDb()
 
279
 
 
280
class Solaris(Distro):
 
281
    def __init__(self):
 
282
        self.packageDb = _SolarisPackageDb()
 
283
 
 
284
class JHBuild(Distro):
 
285
    def __init__(self):
 
286
        self.packageDb = JhBuildPackageDb()
 
287
 
 
288
def detectDistro():
 
289
    logger.log("Detecting distribution:", newline = False)
 
290
 
 
291
    if os.environ.get("CERTIFIED_GNOMIE", "no") == "yes":
 
292
        distro = JHBuild()
 
293
    elif os.path.exists("/etc/SuSE-release"):
 
294
        distro = Suse()
 
295
    elif os.path.exists("/etc/fedora-release"):
 
296
        distro = Fedora()
 
297
    elif os.path.exists("/etc/redhat-release"):
 
298
        distro = RHEL()
 
299
    elif os.path.exists("/usr/share/doc/ubuntu-minimal"):
 
300
        distro = Ubuntu()
 
301
    elif os.path.exists("/etc/debian_version"):
 
302
        distro = Debian()
 
303
    elif os.path.exists("/etc/gentoo-release"):
 
304
        distro = Gentoo()
 
305
    elif os.path.exists("/etc/slackware-version"):
 
306
        raise DistributionNotSupportedError("Slackware")
 
307
    elif os.path.exists("/var/lib/conarydb/conarydb"):
 
308
        distro = Conary()
 
309
    elif os.path.exists ("/etc/release") and \
 
310
            re.match(".*Solaris", open ("/etc/release").readline()):
 
311
        distro = Solaris()
 
312
    else:
 
313
        raise DistributionNotSupportedError("Unknown")
 
314
    logger.log(distro.__class__.__name__)
 
315
    return distro
 
316
 
 
317
distro = detectDistro()
 
318
packageDb = distro.packageDb
 
319