From aa591fef94eb440c6e5a30769f78144ca2168180 Mon Sep 17 00:00:00 2001 From: Thomas Hurst Date: Sat, 30 Aug 2008 00:57:35 +0100 Subject: [PATCH] Improve installation somewhat; allow the use of --record files for uninstallation, and run gtk-update-icon-cache unless we're told otherwise. Update INSTALL to detail this. --- INSTALL | 55 +++++++++++++++++++++++++++++++++-------- setup.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 115 insertions(+), 15 deletions(-) diff --git a/INSTALL b/INSTALL index ea2e7e49..6cb2e8ff 100644 --- a/INSTALL +++ b/INSTALL @@ -1,15 +1,50 @@ -If at all possible I would encourage you to use a distribution -package of Terminator rather than the source tarball (ie I hope -that most users never read this file). -You can find instructions for many distributions at: +It's strongly recommended to install Terminator using your OS's package +system rather than using setup.py yourself. You can find instructions +for many distributions at: http://www.tenshu.net/terminator/ -If you must install from source, install python vte bindings -("python-vte" on Debian/ubuntu) and run: +If you don't have this option, please make sure you satisfy Terminator's +dependencies yourself: - ./setup.py install + * Python 2.4+, 2.5 recommended: + Debian/Ubuntu: python + FreeBSD: lang/python25 -Note that this is not as complete as a package install at the moment -e.g. GNOME menu/icon integration will not happen and there is no -uninstall option. + * Python VTE bindings: + Debian/Ubuntu: python-vte + FreeBSD: x11-toolkits/py-vte + +If you want gnome-terminal profile support, you also need: + + * Python GNOME 2 bindings: + Debian/Ubuntu: python-gnome2 + FreeBSD: x11-toolkits/py-gnome2 + +If you don't care about native language support or icons, Terminator +should run just fine directly from this directory, just: + + ./terminator --help + +And go from there. Manpages are available in the 'doc' directory. + +To install properly, run: + + ./setup.py install --record=install-files.txt + +See --help for an overview of the available options; e.g. --prefix to +install to a custom base directory, and --without-gettext to avoid +installing natural language support files. + +setup.py supports basic uninstallation provided --record was used for +installation as above: + + ./setup.py uninstall --manifest=install-files.txt + +Note that uninstall will avoid removing most empty directories so it +won't harm e.g. locale or icon directories which only contain Terminator +data. It also won't rebuild the icon cache, so you may wish to: + + gtk-update-icon-cache -q -f ${PREFIX}/share/icons/hicolor + +Where ${PREFIX} is the base install directory; e.g. /usr/local. diff --git a/setup.py b/setup.py index 04fff9b5..4ea1fa73 100755 --- a/setup.py +++ b/setup.py @@ -2,10 +2,11 @@ from distutils.core import setup from distutils.dist import Distribution +from distutils.cmd import Command from distutils.command.install_data import install_data from distutils.command.build import build from distutils.dep_util import newer -from distutils.log import info +from distutils.log import warn, info, error, fatal import glob import os import sys @@ -19,10 +20,12 @@ MO_DIR = os.path.join('build', 'mo') class TerminatorDist(Distribution): global_options = Distribution.global_options + [ - ("without-gettext", None, "Don't build/install gettext .mo files")] + ("without-gettext", None, "Don't build/install gettext .mo files"), + ("without-icon-cache", None, "Don't attempt to run gtk-update-icon-cache")] def __init__ (self, *args): self.without_gettext = False + self.without_icon_cache = False Distribution.__init__(self, *args) @@ -49,16 +52,78 @@ class BuildData(build): if rc != 0: raise Warning, "msgfmt returned %d" % rc except Exception, e: - print "Building gettext files failed. Try setup.py --without-gettext [build|install]" - print "%s: %s" % (type(e), e) + error("Building gettext files failed. Try setup.py --without-gettext [build|install]") + error("Error: %s" % str(e)) sys.exit(1) +class Uninstall(Command): + description = "Attempt an uninstall from an install --record file" + + user_options = [('manifest=', None, 'Installation record filename')] + + def initialize_options(self): + self.manifest = None + + def finalize_options(self): + pass + + def get_command_name(self): + return 'uninstall' + + def run(self): + self.ensure_filename('manifest') + try: + f = open(self.manifest) + files = [file.strip() for file in f] + except IOError, e: + raise DistutilsFileError("unable to open install manifest: %s", str(e)) + finally: + f.close() + + for file in files: + if os.path.isfile(file) or os.path.islink(file): + info("removing %s" % repr(file)) + if not self.dry_run: + try: + os.unlink(file) + except OSError, e: + warn("could not delete: %s" % repr(file)) + elif not os.path.isdir(file): + info("skipping %s" % repr(file)) + + dirs = set() + for file in reversed(sorted(files)): + dir = os.path.dirname(file) + if dir not in dirs and os.path.isdir(dir) and len(os.listdir(dir)) == 0: + dirs.add(dir) + # Only nuke empty Python library directories, else we could destroy + # e.g. locale directories we're the only app with a .mo installed for. + if dir.find("site-packages/") > 0: + info("removing %s" % repr(dir)) + if not self.dry_run: + try: + os.rmdir(dir) + except OSError, e: + warn("could not remove directory: %s" % str(e)) + else: + info("skipping empty directory %s" % repr(dir)) + + class InstallData(install_data): def run (self): self.data_files.extend (self._find_mo_files ()) install_data.run (self) + if not self.distribution.without_icon_cache: + self._update_icon_cache () + # We should do this on uninstall too + def _update_icon_cache(self): + info("running gtk-update-icon-cache") + try: + subprocess.call(["gtk-update-icon-cache", "-q", "-f", "-t", os.path.join(self.install_dir, "share/icons/hicolor")]) + except Exception, e: + warn("updating the GTK icon cache failed: %s" % str(e)) def _find_mo_files (self): data_files = [] @@ -98,7 +163,7 @@ setup(name='Terminator', ('share/icons/hicolor/16x16/actions', glob.glob('data/icons/16x16/actions/*.png')), ], packages=['terminatorlib'], - cmdclass={'build': BuildData, 'install_data': InstallData}, + cmdclass={'build': BuildData, 'install_data': InstallData, 'uninstall': Uninstall}, distclass=TerminatorDist )