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