Package dogtail :: Module distro
[hide private]
[frames] | no frames]

Source Code for Module dogtail.distro

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