#!/usr/bin/env python """ **************************************************************************** install.py, Linux install script for TreeLine Copyright (C) 2005, Douglas W. Bell This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, Version 2. This program is distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. ***************************************************************************** """ import sys, os.path, getopt, shutil, compileall, py_compile, glob, re prefixDir = '/usr/local' buildRoot = '/' progName = 'treeline' docDir = 'share/doc/%s' % progName iconDir = 'share/icons/%s' % progName testXML = 1 testSpell = 1 def usage(exitCode=2): """Display usage info and exit""" global prefixDir global buildRoot print 'Usage:' print ' python install.py [-h] [-p dir] [-d dir] [-b dir] [-x]' print 'where:' print ' -h display this help message' print ' -p dir install prefix [default: %s]' % prefixDir print ' -d dir documentaion dir [default: /%s]' % docDir print ' -i dir icon dir [default: /%s]' % iconDir print ' -b dir temporary build root for packagers [default: %s]' \ % buildRoot print ' -x skip all dependency checks (risky)' sys.exit(exitCode) def cmpVersions(versionStr, reqdTuple): """Return 1 if point-sep values in versionStr are >= reqdTuple""" match = re.search(r'[0-9\.]+', versionStr) if not match: return 0 versionStr = match.group() versionList = [int(val) for val in versionStr.split('.') if val] reqdList = list(reqdTuple) while len(versionList) < len(reqdList): versionList.append(0) while len(reqdList) < len(versionList): reqdList.append(0) if cmp(versionList, reqdList) != -1: return 1 return 0 def copyDir(srcDir, dstDir): """Copy all regular files from srcDir to dstDir, dstDir is created if necessary""" try: if not os.path.isdir(dstDir): os.makedirs(dstDir) names = os.listdir(srcDir) for name in names: srcPath = os.path.join(srcDir, name) if os.path.isfile(srcPath): shutil.copy2(srcPath, os.path.join(dstDir, name)) except (IOError, OSError), e: if str(e).find('Permission denied') >= 0: print 'Error - must be root to install files' cleanSource() sys.exit(4) raise def createWrapper(execDir, execName): """Create a wrapper executable file for a python script in execDir named execName""" text = '#!/bin/sh\n\nexec %s %s/%s.py "$@"' % (sys.executable, execDir, \ execName) f = open(execName, 'w') f.write(text) f.close() os.chmod(execName, 0755) def replaceLine(path, origLineStart, newLine): """Searches for origLineStart in file named path, replaces all ocurrances with newLine and re-writes file""" f = open(path, 'r') lines = f.readlines() f.close() f = open(path, 'w') for line in lines: if line.startswith(origLineStart): f.write(newLine) else: f.write(line) f.close() def spellCheck(cmdList): """Try spell checkers from list, print result""" for cmd in cmdList: try: stdIn, stdOut, stdErr = os.popen3(cmd) stdOut.readline() # read header stdIn.write('!\n') # set terse mode stdIn.flush() stdIn.close() stdOut.close() print ' Spell Checker %s -> OK' % cmd.split()[0] return except: pass print ' Spell Checker not found -> install aspell or ispell' print ' if spell checking is desired' def cleanSource(): """Remove any temporary files added to untarred dirs""" for name in glob.glob(os.path.join('source', '*.py[co]')): os.remove(name) global progName if os.path.isfile(progName): os.remove(progName) def removeDir(dir): """Remove dir and all files at path, ignore errors""" try: shutil.rmtree(dir, 1) except: # shouldn't be needed with ignore error param, but pass # some python versions have a bug def main(): optLetters = 'hp:d:i:b:x' try: opts, args = getopt.getopt(sys.argv[1:], optLetters) except getopt.GetoptError: usage(2) global prefixDir global docDir global iconDir global buildRoot global progName depCheck = 1 for opt, val in opts: if opt == '-h': usage(0) elif opt == '-p': prefixDir = os.path.abspath(val) elif opt == '-d': docDir = val elif opt == '-i': iconDir = val elif opt == '-b': buildRoot = val elif opt == '-x': depCheck = 0 if not os.path.isfile('install.py'): print 'Error - %s files not found' % progName print 'The directory containing "install.py" must be current' sys.exit(4) if depCheck: print 'Checking dependencies...' try: pyVersion = sys.version_info[:3] except AttributeError: print ' Python Version 1.x -> Sorry, 2.3 or higher is required' sys.exit(3) pyVersion = '.'.join([str(num) for num in pyVersion]) if cmpVersions(pyVersion, (2, 3)): print ' Python Version %s -> OK' % pyVersion else: print ' Python Version %s -> Sorry, 2.3 or higher is required' \ % pyVersion sys.exit(3) try: from qt import qVersion, PYQT_VERSION except: print ' Sorry, PyQt must be installed' sys.exit(3) qtVersion = qVersion() if cmpVersions(qtVersion, (2, 3)): print ' Qt Version %s -> OK' % qtVersion else: print ' Qt Version %s -> Sorry, 2.3 or higher is required' \ % qtVersion sys.exit(3) try: from qt import PYQT_VERSION_STR pyqtVersion = PYQT_VERSION_STR except: pyqtVersion = PYQT_VERSION if cmpVersions(pyqtVersion, (2, 4)): print ' PyQt Version %s -> OK' % pyqtVersion else: print ' PyQt Version %s -> Sorry, 2.4 or higher is required' \ % pyqtVersion sys.exit(3) global testXML if testXML: try: import xml.sax handler = xml.sax.ContentHandler() xml.sax.parseString('test', handler) except: print ' XML Parser -> Sorry, the expat library or '\ 'PyXML package is required' sys.exit(3) print ' XML Parser -> OK' global testSpell if testSpell: spellCheck(['aspell -a', 'ispell -a']) pythonPrefixDir = os.path.join(prefixDir, 'lib', progName) pythonBuildDir = os.path.join(buildRoot, pythonPrefixDir[1:]) if os.path.isdir('source'): compileall.compile_dir('source', ddir=os.path.join(prefixDir, 'source')) print 'Installing files...' print ' Copying python files to %s' % pythonBuildDir removeDir(pythonBuildDir) # remove old? copyDir('source', pythonBuildDir) if os.path.isdir(os.path.join('source', 'plugins')): pluginBuildDir = os.path.join(pythonBuildDir, 'plugins') print ' Creating plugins directory if necessary' copyDir(os.path.join('source', 'plugins'), pluginBuildDir) if os.path.isdir('translations'): translationDir = os.path.join(pythonBuildDir, 'translations') print ' Copying translation files to %s' % translationDir copyDir('translations', translationDir) if os.path.isdir('doc'): docPrefixDir = docDir.replace('/', '') if not os.path.isabs(docPrefixDir): docPrefixDir = os.path.join(prefixDir, docPrefixDir) docBuildDir = os.path.join(buildRoot, docPrefixDir[1:]) print ' Copying documentation files to %s' % docBuildDir copyDir('doc', docBuildDir) # update help file location in main python script replaceLine(os.path.join(pythonBuildDir, '%s.py' % progName), \ 'helpFilePath = None', \ 'helpFilePath = \'%s\' # modified by install script\n' \ % docPrefixDir) if os.path.isdir('data'): dataPrefixDir = os.path.join(prefixDir, 'share', progName) dataBuildDir = os.path.join(buildRoot, dataPrefixDir[1:]) print ' Copying data files to %s' % dataBuildDir removeDir(dataBuildDir) # remove old? copyDir('data', dataBuildDir) # update data file location in main python script replaceLine(os.path.join(pythonBuildDir, '%s.py' % progName), \ 'dataFilePath = None', \ 'dataFilePath = \'%s\' # modified by install script\n' \ % dataPrefixDir) if os.path.isdir('icons'): iconPrefixDir = iconDir.replace('/', '') if not os.path.isabs(iconPrefixDir): iconPrefixDir = os.path.join(prefixDir, iconPrefixDir) iconBuildDir = os.path.join(buildRoot, iconPrefixDir[1:]) print ' Copying icon files to %s' % iconBuildDir copyDir('icons', iconBuildDir) # update icon location in main python script replaceLine(os.path.join(pythonBuildDir, '%s.py' % progName), \ 'iconPath = None', \ 'iconPath = \'%s\' # modified by install script\n' \ % iconPrefixDir) if os.path.isdir('source'): createWrapper(pythonPrefixDir, progName) binBuildDir = os.path.join(buildRoot, prefixDir[1:], 'bin') print ' Copying executable file "%s" to %s' % (progName, binBuildDir) if not os.path.isdir(binBuildDir): os.makedirs(binBuildDir) shutil.copy2(progName, binBuildDir) cleanSource() print 'Install complete.' if __name__ == '__main__': main()