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 -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):
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):
267
268 -class Suse(Distro):
269 - def __init__(self):
270 self.packageDb = _RpmPackageDb()
271
272 -class Gentoo(Distro):
273 - def __init__(self):
275
276 -class Conary(Distro):
277 - def __init__(self):
279
280 -class Solaris(Distro):
281 - def __init__(self):
283
284 -class JHBuild(Distro):
285 - def __init__(self):
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