#! /usr/bin/python import glob, logging, os, re, string, sys, time, cStringIO from optparse import OptionParser from ConfigParser import SafeConfigParser sys.path[0:0] = ['/usr/share/pycentral-data', '/usr/share/python'] import pyversions try: SetType = set except NameError: import sets SetType = sets.Set set = sets.Set program = os.path.basename(sys.argv[0]) shared_base = '/usr/share/pycentral/' shared_base2 = '/usr/share/pyshared/' pycentral_version = '0.6.16' req_pycentral_version = '0.6.15' def get_file_overwrite_error(existing_files): """ helper that returns a error string to be passed to the user when local files are detected (and querries if they are local installs or part of another package) """ from subprocess import PIPE, Popen l = [] # ask dpkg what it knows about the files in question (stdout, stderr) = Popen(["dpkg","-S"]+existing_files, env={"LANG" : "C"}, stdout=PIPE, stderr=PIPE).communicate() # this should never happen, dpkg should always give us # something but we deal with it for robustness if not stdout and not stderr: l.append("Error, can not overwrite existing files:") l.extend(existing_files) # stdout has files that belong to packages if stdout: l.append("Not overwriting files owned by other packages:") for line in map(string.strip, stdout.split("\n")): if line: l.append(" "+line) # stderr has local (or maintainer script created) files if stderr: l.append("Not overwriting local files:") for line in map(string.strip, stderr.split("\n")): if line: l.append(" "+line) return "\n".join(l) def samefs(path1, path2): if not (os.path.exists(path1) and os.path.exists(path2)): return False while path1 != os.path.dirname(path1): if os.path.ismount(path1): break path1 = os.path.dirname(path1) while path2 != os.path.dirname(path2): if os.path.ismount(path2): break path2 = os.path.dirname(path2) return path1 == path2 def version2depends(vinfo): if isinstance(vinfo, set): vinfo = list(vinfo) if isinstance(vinfo, list): vinfo = vinfo[:] vinfo.sort() nv = [int(s) for s in vinfo[-1].split('.')] deps = 'python (>= %s), python (<< %d.%d)' % (vinfo[0], nv[0], nv[1]+1) elif vinfo in ('all', 'current'): supported = [d[6:] for d in pyversions.supported_versions() if re.match(r'python\d\.\d', d)] supported.sort() deps = 'python (>= %s)' % supported[0] elif vinfo == 'current_ext': cv = pyversions.default_version(version_only=True) nv = [int(s) for s in cv.split('.')] deps = 'python (>= %s), python (<< %d.%d)' % (cv, nv[0], nv[1]+1) else: raise ValueError, 'unknown version info %s' % vinfo return deps + ', python-central (>= %s)' % req_pycentral_version def third_party_dir(version): if version.startswith('python'): version = version[6:] if version in ('2.3', '2.4', '2.5'): return 'usr/lib/python' + version + '/site-packages' else: return 'usr/lib/python' + version + '/dist-packages' def build_relative_link(tgt, link): t = tgt.split('/') l = link.split('/') while l[0] == t[0]: del l[0], t[0] return '/'.join(['..' for i in range(len(l)-1)] + t) def read_dpkg_status(verbose=False): """Read the dpkg status file, return a list of packages depending on python-central and having a Python-Version information field.""" packages = [] rx = re.compile(r'\bpython-central\b') pkgname = version = None depends = '' status = [] for line in file('/var/lib/dpkg/status'): if line.startswith('Package:'): if version != None and 'installed' in status: if 'python-support' in depends: pass elif rx.search(depends): packages.append((pkgname, version)) if verbose: print " %s: %s (%s)" % (pkgname, version, status) version = None status = [] pkgname = line.split(':', 1)[1].strip() elif line.startswith('Python-Version:'): version = line.split(':', 1)[1].strip() elif line.startswith('Depends:'): depends = line.split(':', 1)[1].strip() elif line.startswith('Status:'): status = line.split(':', 1)[1].strip().split() if version != None and 'installed' in status: if rx.search(depends): packages.append((pkgname, version)) if verbose: print " %s: %s (%s)" % (pkgname, version, status) return packages class PyCentralConfigParser(SafeConfigParser): '''SafeConfigParser allowing mixed case, `:' and `=' in keys''' OPTCRE = re.compile( r'(?P