#!/usr/bin/env python # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai from __future__ import with_statement __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' import sys, os, textwrap, subprocess, shutil, tempfile, atexit, stat from setup import Command, islinux, basenames, modules, functions, \ __appname__, __version__ HEADER = '''\ #!/usr/bin/env python """ This is the standard runscript for all of calibre's tools. Do not modify it unless you know what you are doing. """ import sys, os path = os.environ.get('CALIBRE_PYTHON_PATH', {path!r}) sys.path.insert(0, path) sys.resources_location = os.environ.get('CALIBRE_RESOURCES_PATH', {resources!r}) sys.extensions_location = os.environ.get('CALIBRE_EXTENSIONS_PATH', {extensions!r}) ''' TEMPLATE = HEADER+''' from {module} import {func!s} sys.exit({func!s}()) ''' COMPLETE_TEMPLATE = HEADER+''' sys.path.insert(0, os.path.join(path, 'calibre', 'utils')) import complete sys.path = sys.path[1:] sys.exit(complete.main()) ''' class Develop(Command): description = textwrap.dedent('''\ Setup a development environment for calibre. This allows you to run calibre directly from the source tree. Binaries will be installed in /bin where is the prefix of your python installation. This can be controlled via the --prefix option. ''') short_description = 'Setup a development environment for calibre' MODE = 0755 sub_commands = ['build', 'resources', 'gui'] def add_postinstall_options(self, parser): parser.add_option('--make-errors-fatal', action='store_true', default=False, dest='fatal_errors', help='If set die on post install errors.') parser.add_option('--no-postinstall', action='store_false', dest='postinstall', default=True, help='Don\'t run post install actions like creating MAN pages, setting'+ ' up desktop integration and so on') def add_options(self, parser): parser.add_option('--prefix', help='Binaries will be installed in /bin') self.add_postinstall_options(parser) def consolidate_paths(self): opts = self.opts if not opts.prefix: opts.prefix = sys.prefix self.libdir = getattr(opts, 'libdir', None) if self.libdir is None: self.libdir = self.j(opts.prefix, 'lib') self.bindir = getattr(opts, 'bindir', None) if self.bindir is None: self.bindir = self.j(opts.prefix, 'bin') self.sharedir = getattr(opts, 'sharedir', None) if self.sharedir is None: self.sharedir = self.j(opts.prefix, 'share') if not getattr(opts, 'staging_root', None): opts.staging_root = opts.prefix self.staging_libdir = getattr(opts, 'staging_libdir', None) if self.staging_libdir is None: self.staging_libdir = opts.staging_libdir = self.j(opts.staging_root, 'lib') self.staging_bindir = getattr(opts, 'staging_bindir', None) if self.staging_bindir is None: self.staging_bindir = opts.staging_bindir = self.j(opts.staging_root, 'bin') self.staging_sharedir = getattr(opts, 'staging_sharedir', None) if self.staging_sharedir is None: self.staging_sharedir = opts.staging_sharedir = self.j(opts.staging_root, 'share') self.staging_libdir = opts.staging_libdir = self.j(self.staging_libdir, 'calibre') self.staging_sharedir = opts.staging_sharedir = self.j(self.staging_sharedir, 'calibre') if self.__class__.__name__ == 'Develop': self.libdir = self.SRC self.sharedir = self.RESOURCES else: self.libdir = self.j(self.libdir, 'calibre') self.sharedir = self.j(self.sharedir, 'calibre') self.info('INSTALL paths:') self.info('\tLIB:', self.staging_libdir) self.info('\tSHARE:', self.staging_sharedir) def pre_sub_commands(self, opts): if not islinux: self.info('\nSetting up a source based development environment is only ' 'supported on linux. On other platforms, see the User Manual' ' for help with setting up a development environment.') raise SystemExit(1) if os.geteuid() == 0: self.drop_privileges() # Ensure any calibre config files are created as correct user import calibre.utils.config as c c def run(self, opts): self.manifest = [] self.opts = opts self.regain_privileges() self.consolidate_paths() self.write_templates() self.setup_mount_helper() self.install_files() self.run_postinstall() self.success() def setup_mount_helper(self): def warn(): self.warn('Failed to compile mount helper. Auto mounting of', ' devices will not work') if os.geteuid() != 0: return self.warn('Must be run as root to compile mount helper. Auto ' 'mounting of devices will not work.') src = os.path.join(self.SRC, 'calibre', 'devices', 'linux_mount_helper.c') dest = os.path.join(self.staging_bindir, 'calibre-mount-helper') self.info('Installing mount helper to '+ dest) p = subprocess.Popen(['gcc', '-Wall', '-pedantic', src, '-o', dest]) ret = p.wait() if ret != 0: return warn() os.chown(dest, 0, 0) os.chmod(dest, stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|\ stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH) self.manifest.append(dest) return dest def install_files(self): pass def run_postinstall(self): if self.opts.postinstall: from calibre.linux import PostInstall PostInstall(self.opts, info=self.info, warn=self.warn, manifest=self.manifest) def success(self): self.info('\nDevelopment environment successfully setup') def write_templates(self): for typ in ('console', 'gui'): for name, mod, func in zip(basenames[typ], modules[typ], functions[typ]): self.write_template(name, mod, func) def write_template(self, name, mod, func): template = COMPLETE_TEMPLATE if name == 'calibre-complete' else TEMPLATE script = template.format( module=mod, func=func, path=self.libdir, resources=self.sharedir, extensions=self.j(self.libdir, 'calibre', 'plugins')) path = self.j(self.staging_bindir, name) if not os.path.exists(self.staging_bindir): os.makedirs(self.staging_bindir) self.info('Installing binary:', path) open(path, 'wb').write(script) os.chmod(path, self.MODE) self.manifest.append(path) class Install(Develop): description = textwrap.dedent('''\ Install calibre to your system. By default, calibre is installed to /bin, /lib/calibre, /share/calibre. These can all be controlled via options. The default is the prefix of your python installation. ''') short_description = 'Install calibre from source' sub_commands = ['build', 'gui'] def add_options(self, parser): parser.add_option('--prefix', help='Installation prefix.') parser.add_option('--libdir', help='Where to put calibre library files. Default is /lib') parser.add_option('--bindir', help='Where to put the calibre binaries. Default is /bin') parser.add_option('--sharedir', help='Where to put the calibre data files. Default is /share') parser.add_option('--staging-root', '--root', default=None, help=('Use a different installation root (mainly for packaging).' ' The prefix option controls the paths written into ' 'the launcher scripts. This option controls the prefix ' 'to which the install will actually copy files. By default ' 'it is set to the value of --prefix.')) parser.add_option('--staging-libdir', help='Where to put calibre library files. Default is /lib') parser.add_option('--staging-bindir', help='Where to put the calibre binaries. Default is /bin') parser.add_option('--staging-sharedir', help='Where to put the calibre data files. Default is /share') self.add_postinstall_options(parser) def install_files(self): dest = self.staging_libdir if os.path.exists(dest): shutil.rmtree(dest) for x in os.walk(self.SRC): reldir = os.path.relpath(x[0], self.SRC) destdir = os.path.join(dest, reldir) for f in x[-1]: if os.path.splitext(f)[1] in ('.py', '.so'): if not os.path.exists(destdir): os.makedirs(destdir) shutil.copy2(self.j(x[0], f), destdir) dest = self.staging_sharedir if os.path.exists(dest): shutil.rmtree(dest) shutil.copytree(self.RESOURCES, dest) self.manifest.extend([self.staging_libdir, self.staging_sharedir]) def success(self): self.info('\n\ncalibre successfully installed. You can start' ' it by running the command calibre') class Sdist(Command): description = 'Create a source distribution' DEST = os.path.join('dist', '%s-%s.tar.gz'%(__appname__, __version__)) def run(self, opts): if not self.e(self.d(self.DEST)): os.makedirs(self.d(self.DEST)) tdir = tempfile.mkdtemp() tdir = self.j(tdir, 'calibre') atexit.register(shutil.rmtree, tdir) self.info('\tRunning bzr export...') subprocess.check_call(['bzr', 'export', '--format', 'dir', tdir]) for x in open('.bzrignore').readlines(): if not x.startswith('resources/'): continue p = x.strip().replace('/', os.sep) d = self.j(tdir, os.path.dirname(p)) if not self.e(d): os.makedirs(d) if os.path.isdir(p): shutil.copytree(p, self.j(tdir, p)) else: shutil.copy2(p, d) for x in os.walk(os.path.join(self.SRC, 'calibre')): for f in x[-1]: if not f.endswith('_ui.py'): continue f = os.path.join(x[0], f) f = os.path.relpath(f) dest = os.path.join(tdir, self.d(f)) shutil.copy2(f, dest) self.info('\tCreating tarfile...') subprocess.check_call(['tar', '-czf', self.a(self.DEST), 'calibre'], cwd=self.d(tdir)) def clean(self): if os.path.exists(self.DEST): os.remove(self.DEST)