mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix #3523 (Please re-add ./setup.py install --root option) and clean up install/post-install code. Post install now no longer runs in a separate process.
This commit is contained in:
parent
0ff0ce51e8
commit
ef06fbee81
11
setup.py
11
setup.py
@ -41,7 +41,14 @@ def clean_backups():
|
|||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
if len(args) == 1 or args[1] in ('-h', '--help'):
|
if len(args) == 1 or args[1] in ('-h', '--help'):
|
||||||
print 'Usage: python', args[0], 'command', '[options]'
|
print 'Usage: python', args[0], 'command', '[options]'
|
||||||
print '\nWhere command is one of:', ', '.join(commands.__all__)
|
print '\nWhere command is one of:'
|
||||||
|
print
|
||||||
|
for x in sorted(commands.__all__):
|
||||||
|
print '%-20s -'%x,
|
||||||
|
c = getattr(commands, x)
|
||||||
|
desc = getattr(c, 'short_description', c.description)
|
||||||
|
print desc
|
||||||
|
|
||||||
print '\nTo get help on a particular command, run:'
|
print '\nTo get help on a particular command, run:'
|
||||||
print '\tpython', args[0], 'command -h'
|
print '\tpython', args[0], 'command -h'
|
||||||
return 1
|
return 1
|
||||||
@ -83,7 +90,7 @@ def main(args=sys.argv):
|
|||||||
prints('There were', len(warnings), 'warning(s):')
|
prints('There were', len(warnings), 'warning(s):')
|
||||||
print
|
print
|
||||||
for args, kwargs in warnings:
|
for args, kwargs in warnings:
|
||||||
prints(*args, **kwargs)
|
prints('*', *args, **kwargs)
|
||||||
print
|
print
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
@ -111,6 +111,7 @@ class Command(object):
|
|||||||
self.b = os.path.basename
|
self.b = os.path.basename
|
||||||
self.s = os.path.splitext
|
self.s = os.path.splitext
|
||||||
self.e = os.path.exists
|
self.e = os.path.exists
|
||||||
|
self.orig_euid = os.geteuid()
|
||||||
self.real_uid = os.environ.get('SUDO_UID', None)
|
self.real_uid = os.environ.get('SUDO_UID', None)
|
||||||
self.real_gid = os.environ.get('SUDO_GID', None)
|
self.real_gid = os.environ.get('SUDO_GID', None)
|
||||||
self.real_user = os.environ.get('SUDO_USER', None)
|
self.real_user = os.environ.get('SUDO_USER', None)
|
||||||
@ -121,19 +122,19 @@ class Command(object):
|
|||||||
if self.real_user is not None:
|
if self.real_user is not None:
|
||||||
self.info('Dropping privileges to those of', self.real_user+':',
|
self.info('Dropping privileges to those of', self.real_user+':',
|
||||||
self.real_uid)
|
self.real_uid)
|
||||||
|
if self.real_gid is not None:
|
||||||
|
os.setegid(int(self.real_gid))
|
||||||
if self.real_uid is not None:
|
if self.real_uid is not None:
|
||||||
os.seteuid(int(self.real_uid))
|
os.seteuid(int(self.real_uid))
|
||||||
#if self.real_gid is not None:
|
|
||||||
# os.setegid(int(self.real_gid))
|
|
||||||
|
|
||||||
def regain_privileges(self):
|
def regain_privileges(self):
|
||||||
if not islinux or isosx:
|
if not islinux or isosx:
|
||||||
return
|
return
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0 and self.orig_euid == 0:
|
||||||
self.info('Trying to get root privileges')
|
self.info('Trying to get root privileges')
|
||||||
os.seteuid(0)
|
os.seteuid(0)
|
||||||
#if os.getegid() != 0:
|
if os.getegid() != 0:
|
||||||
# os.setegid(0)
|
os.setegid(0)
|
||||||
|
|
||||||
def pre_sub_commands(self, opts):
|
def pre_sub_commands(self, opts):
|
||||||
pass
|
pass
|
||||||
|
@ -37,6 +37,8 @@ def check_for_python_errors(filename, builtins):
|
|||||||
|
|
||||||
class Check(Command):
|
class Check(Command):
|
||||||
|
|
||||||
|
description = 'Check for errors in the calibre source code'
|
||||||
|
|
||||||
BUILTINS = ['_', '__', 'dynamic_property', 'I', 'P']
|
BUILTINS = ['_', '__', 'dynamic_property', 'I', 'P']
|
||||||
CACHE = '.check-cache.pickle'
|
CACHE = '.check-cache.pickle'
|
||||||
|
|
||||||
|
@ -175,6 +175,8 @@ if iswindows:
|
|||||||
|
|
||||||
class Build(Command):
|
class Build(Command):
|
||||||
|
|
||||||
|
short_description = 'Build calibre C/C++ extension modules'
|
||||||
|
|
||||||
description = textwrap.dedent('''\
|
description = textwrap.dedent('''\
|
||||||
calibre depends on several python extensions written in C/C++.
|
calibre depends on several python extensions written in C/C++.
|
||||||
This command will compile them. You can influence the compile
|
This command will compile them. You can influence the compile
|
||||||
|
200
setup/install.py
200
setup/install.py
@ -6,7 +6,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys, os, textwrap, subprocess, shutil, tempfile, atexit
|
import sys, os, textwrap, subprocess, shutil, tempfile, atexit, stat
|
||||||
|
|
||||||
from setup import Command, islinux, basenames, modules, functions, \
|
from setup import Command, islinux, basenames, modules, functions, \
|
||||||
__appname__, __version__
|
__appname__, __version__
|
||||||
@ -19,28 +19,26 @@ This is the standard runscript for all of calibre's tools.
|
|||||||
Do not modify it unless you know what you are doing.
|
Do not modify it unless you know what you are doing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
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+'''
|
TEMPLATE = HEADER+'''
|
||||||
sys.path.insert(0, {path!r})
|
|
||||||
|
|
||||||
sys.resources_location = {resources!r}
|
|
||||||
sys.extensions_location = {extensions!r}
|
|
||||||
|
|
||||||
from {module} import {func!s}
|
from {module} import {func!s}
|
||||||
sys.exit({func!s}())
|
sys.exit({func!s}())
|
||||||
'''
|
'''
|
||||||
|
|
||||||
COMPLETE_TEMPLATE = HEADER+'''
|
COMPLETE_TEMPLATE = HEADER+'''
|
||||||
import os
|
sys.path.insert(0, os.path.join(path, 'calibre', 'utils'))
|
||||||
sys.path.insert(0, {path!r})
|
|
||||||
sys.path.insert(0, os.path.join({path!r}, 'calibre', 'utils'))
|
|
||||||
import complete
|
import complete
|
||||||
sys.path = sys.path[1:]
|
sys.path = sys.path[1:]
|
||||||
|
|
||||||
sys.resources_location = {resources!r}
|
|
||||||
sys.extensions_location = {extensions!r}
|
|
||||||
sys.exit(complete.main())
|
sys.exit(complete.main())
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -53,93 +51,123 @@ class Develop(Command):
|
|||||||
the prefix of your python installation. This can be controlled
|
the prefix of your python installation. This can be controlled
|
||||||
via the --prefix option.
|
via the --prefix option.
|
||||||
''')
|
''')
|
||||||
|
short_description = 'Setup a development environment for calibre'
|
||||||
MODE = 0755
|
MODE = 0755
|
||||||
|
|
||||||
sub_commands = ['build', 'resources', 'gui']
|
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):
|
def add_options(self, parser):
|
||||||
parser.add_option('--prefix',
|
parser.add_option('--prefix',
|
||||||
help='Binaries will be installed in <prefix>/bin')
|
help='Binaries will be installed in <prefix>/bin')
|
||||||
self.root = ''
|
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')
|
||||||
|
|
||||||
|
if self.__class__.__name__ == 'Develop':
|
||||||
|
self.libdir = self.SRC
|
||||||
|
self.sharedir = self.RESOURCES
|
||||||
|
|
||||||
def pre_sub_commands(self, opts):
|
def pre_sub_commands(self, opts):
|
||||||
if not islinux:
|
if not islinux:
|
||||||
self.info('\nSetting up a development environment is only '
|
self.info('\nSetting up a source based development environment is only '
|
||||||
'supported on linux. On other platforms, install the calibre '
|
'supported on linux. On other platforms, see the User Manual'
|
||||||
'binary and use the calibre-debug command.')
|
' for help with setting up a development environment.')
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
if not os.geteuid() == 0:
|
if os.geteuid() == 0:
|
||||||
self.info('\nError: This command must be run as root.')
|
self.drop_privileges()
|
||||||
raise SystemExit(1)
|
# Ensure any calibre config files are created as correct user
|
||||||
self.drop_privileges()
|
import calibre.utils.config as c
|
||||||
|
c
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
|
self.opts = opts
|
||||||
self.regain_privileges()
|
self.regain_privileges()
|
||||||
self.find_locations(opts)
|
self.consolidate_paths()
|
||||||
self.write_templates(opts)
|
self.write_templates()
|
||||||
self.setup_mount_helper()
|
self.setup_mount_helper()
|
||||||
self.install_files(opts)
|
self.install_files()
|
||||||
self.run_postinstall()
|
self.run_postinstall()
|
||||||
self.success()
|
self.success()
|
||||||
|
|
||||||
def setup_mount_helper(self):
|
def setup_mount_helper(self):
|
||||||
def warn():
|
def warn():
|
||||||
self.warn('Failed to compile mount helper. Auto mounting of',
|
self.warn('Failed to compile mount helper. Auto mounting of',
|
||||||
'devices will not work')
|
' devices will not work')
|
||||||
|
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
return warn()
|
return self.warn('Must be run as root to compile mount helper. Auto '
|
||||||
import stat
|
'mounting of devices will not work.')
|
||||||
src = os.path.join(self.SRC, 'calibre', 'devices', 'linux_mount_helper.c')
|
src = os.path.join(self.SRC, 'calibre', 'devices', 'linux_mount_helper.c')
|
||||||
dest = self.root + os.path.join(self.bindir, 'calibre-mount-helper')
|
dest = os.path.join(self.staging_bindir, 'calibre-mount-helper')
|
||||||
self.info('Installing mount helper to '+ dest)
|
self.info('Installing mount helper to '+ dest)
|
||||||
p = subprocess.Popen(['gcc', '-Wall', src, '-o', dest])
|
p = subprocess.Popen(['gcc', '-Wall', '-pedantic', src, '-o', dest])
|
||||||
ret = p.wait()
|
ret = p.wait()
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
return warn()
|
return warn()
|
||||||
os.chown(dest, 0, 0)
|
os.chown(dest, 0, 0)
|
||||||
os.chmod(dest,
|
os.chmod(dest, stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|\
|
||||||
stat.S_ISUID|stat.S_ISGID|stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
|
stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
def install_files(self, opts):
|
def install_files(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def run_postinstall(self):
|
def run_postinstall(self):
|
||||||
env = dict(**os.environ)
|
if self.opts.postinstall:
|
||||||
env['DESTDIR'] = self.prefix
|
from calibre.linux import PostInstall
|
||||||
subprocess.check_call(['calibre_postinstall', '--use-destdir'], env=env)
|
PostInstall(self.opts, info=self.info, warn=self.warn)
|
||||||
|
|
||||||
def success(self):
|
def success(self):
|
||||||
self.info('\nDevelopment environment successfully setup')
|
self.info('\nDevelopment environment successfully setup')
|
||||||
|
|
||||||
def find_locations(self, opts):
|
def write_templates(self):
|
||||||
self.prefix = opts.prefix
|
|
||||||
if self.prefix is None:
|
|
||||||
self.prefix = sys.prefix
|
|
||||||
self.path = self.SRC
|
|
||||||
self.resources = self.j(self.d(self.SRC), 'resources')
|
|
||||||
self.extensions = self.j(self.SRC, 'calibre', 'plugins')
|
|
||||||
self.bindir = self.j(self.prefix, 'bin')
|
|
||||||
|
|
||||||
def write_templates(self, opts):
|
|
||||||
for typ in ('console', 'gui'):
|
for typ in ('console', 'gui'):
|
||||||
for name, mod, func in zip(basenames[typ], modules[typ],
|
for name, mod, func in zip(basenames[typ], modules[typ],
|
||||||
functions[typ]):
|
functions[typ]):
|
||||||
self.write_template(opts, name, mod, func)
|
self.write_template(name, mod, func)
|
||||||
if islinux:
|
|
||||||
self.write_template(opts, 'calibre_postinstall', 'calibre.linux', 'main')
|
|
||||||
|
|
||||||
def write_template(self, opts, name, mod, func):
|
def write_template(self, name, mod, func):
|
||||||
template = COMPLETE_TEMPLATE if name == 'calibre-complete' else TEMPLATE
|
template = COMPLETE_TEMPLATE if name == 'calibre-complete' else TEMPLATE
|
||||||
script = template.format(
|
script = template.format(
|
||||||
module=mod, func=func,
|
module=mod, func=func,
|
||||||
path=self.path, resources=self.resources,
|
path=self.libdir, resources=self.sharedir,
|
||||||
extensions=self.extensions)
|
extensions=self.j(self.libdir, 'calibre', 'plugins'))
|
||||||
path = self.root + self.j(self.bindir, name)
|
path = self.j(self.staging_bindir, name)
|
||||||
if not os.path.exists(self.bindir):
|
if not os.path.exists(self.staging_bindir):
|
||||||
os.makedirs(self.bindir)
|
os.makedirs(self.staging_bindir)
|
||||||
self.info('Installing binary:', path)
|
self.info('Installing binary:', path)
|
||||||
open(path, 'wb').write(script)
|
open(path, 'wb').write(script)
|
||||||
os.chmod(path, self.MODE)
|
os.chmod(path, self.MODE)
|
||||||
@ -154,49 +182,45 @@ class Install(Develop):
|
|||||||
|
|
||||||
The default <prefix> is the prefix of your python installation.
|
The default <prefix> is the prefix of your python installation.
|
||||||
''')
|
''')
|
||||||
|
short_description = 'Install calibre from source'
|
||||||
|
|
||||||
sub_commands = ['build', 'gui']
|
sub_commands = ['build', 'gui']
|
||||||
|
|
||||||
def add_options(self, parser):
|
def add_options(self, parser):
|
||||||
parser.add_option('--prefix', help='Installation prefix')
|
parser.add_option('--prefix', help='Installation prefix.')
|
||||||
parser.add_option('--libdir', help='Where to put calibre library files')
|
parser.add_option('--libdir',
|
||||||
parser.add_option('--bindir', help='Where to install calibre binaries')
|
help='Where to put calibre library files. Default is <prefix>/lib')
|
||||||
parser.add_option('--sharedir', help='Where to install calibre data files')
|
parser.add_option('--bindir',
|
||||||
parser.add_option('--root', default='',
|
help='Where to put the calibre binaries. Default is <prefix>/bin')
|
||||||
help='Use a different installation root (mainly for packaging)')
|
parser.add_option('--sharedir',
|
||||||
self.root = ''
|
help='Where to put the calibre data files. Default is <prefix>/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 <root>/lib')
|
||||||
|
parser.add_option('--staging-bindir',
|
||||||
|
help='Where to put the calibre binaries. Default is <root>/bin')
|
||||||
|
parser.add_option('--staging-sharedir',
|
||||||
|
help='Where to put the calibre data files. Default is <root>/share')
|
||||||
|
self.add_postinstall_options(parser)
|
||||||
|
|
||||||
def find_locations(self, opts):
|
def install_files(self):
|
||||||
if opts.prefix is None:
|
dest = self.staging_libdir
|
||||||
opts.prefix = sys.prefix
|
|
||||||
if opts.libdir is None:
|
|
||||||
opts.libdir = self.j(opts.prefix, 'lib', 'calibre')
|
|
||||||
if opts.bindir is None:
|
|
||||||
opts.bindir = self.j(opts.prefix, 'bin')
|
|
||||||
if opts.sharedir is None:
|
|
||||||
opts.sharedir = self.j(opts.prefix, 'share', 'calibre')
|
|
||||||
self.prefix = opts.prefix
|
|
||||||
self.bindir = opts.bindir
|
|
||||||
self.path = opts.libdir
|
|
||||||
self.resources = opts.sharedir
|
|
||||||
self.extensions = self.j(self.path, 'calibre', 'plugins')
|
|
||||||
self.root = opts.root
|
|
||||||
|
|
||||||
def install_files(self, opts):
|
|
||||||
dest = self.root + self.path
|
|
||||||
if os.path.exists(dest):
|
if os.path.exists(dest):
|
||||||
shutil.rmtree(dest)
|
shutil.rmtree(dest)
|
||||||
shutil.copytree(self.SRC, dest)
|
for x in os.walk(self.SRC):
|
||||||
for x in ('calibre/manual', 'calibre/trac',
|
reldir = os.path.relpath(x[0], self.SRC)
|
||||||
'calibre/ebooks/lrf/html/demo'):
|
destdir = os.path.join(dest, reldir)
|
||||||
x = self.j(dest, x)
|
|
||||||
if os.path.exists(dest):
|
|
||||||
shutil.rmtree(x)
|
|
||||||
for x in os.walk(dest):
|
|
||||||
for f in x[-1]:
|
for f in x[-1]:
|
||||||
if os.path.splitext(f)[1] in ('.c', '.cpp', '.h'):
|
if os.path.splitext(f)[1] in ('.py', '.so'):
|
||||||
os.remove(self.j(x[0], f))
|
if not os.path.exists(destdir):
|
||||||
dest = self.root + self.resources
|
os.makedirs(destdir)
|
||||||
|
shutil.copy2(self.j(x[0], f), destdir)
|
||||||
|
dest = self.staging_sharedir
|
||||||
if os.path.exists(dest):
|
if os.path.exists(dest):
|
||||||
shutil.rmtree(dest)
|
shutil.rmtree(dest)
|
||||||
shutil.copytree(self.RESOURCES, dest)
|
shutil.copytree(self.RESOURCES, dest)
|
||||||
|
@ -13,6 +13,8 @@ from setup import Command, installer_name
|
|||||||
|
|
||||||
class Linux32(VMInstaller):
|
class Linux32(VMInstaller):
|
||||||
|
|
||||||
|
description = 'Build 32bit linux binary installer'
|
||||||
|
|
||||||
INSTALLER_EXT = 'tar.bz2'
|
INSTALLER_EXT = 'tar.bz2'
|
||||||
VM_NAME = 'gentoo32_build'
|
VM_NAME = 'gentoo32_build'
|
||||||
VM = '/vmware/bin/gentoo32_build'
|
VM = '/vmware/bin/gentoo32_build'
|
||||||
@ -21,6 +23,8 @@ class Linux32(VMInstaller):
|
|||||||
|
|
||||||
class Linux64(Command):
|
class Linux64(Command):
|
||||||
|
|
||||||
|
description = 'Build 64bit linux binary installer'
|
||||||
|
|
||||||
sub_commands = ['linux_freeze']
|
sub_commands = ['linux_freeze']
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
@ -31,4 +35,6 @@ class Linux64(Command):
|
|||||||
|
|
||||||
class Linux(Command):
|
class Linux(Command):
|
||||||
|
|
||||||
|
description = 'Build linux binary installers'
|
||||||
|
|
||||||
sub_commands = ['linux64', 'linux32']
|
sub_commands = ['linux64', 'linux32']
|
||||||
|
@ -12,6 +12,8 @@ from setup.installer import VMInstaller
|
|||||||
|
|
||||||
class OSX(Command):
|
class OSX(Command):
|
||||||
|
|
||||||
|
description = 'Build OS X binary installers'
|
||||||
|
|
||||||
sub_commands = ['osx32']
|
sub_commands = ['osx32']
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
@ -20,6 +22,8 @@ class OSX(Command):
|
|||||||
|
|
||||||
class OSX32(VMInstaller):
|
class OSX32(VMInstaller):
|
||||||
|
|
||||||
|
description = 'Build 32 bit OS X binary installer'
|
||||||
|
|
||||||
INSTALLER_EXT = 'dmg'
|
INSTALLER_EXT = 'dmg'
|
||||||
VM_NAME = 'tiger_build'
|
VM_NAME = 'tiger_build'
|
||||||
VM = '/vmware/bin/%s'%VM_NAME
|
VM = '/vmware/bin/%s'%VM_NAME
|
||||||
|
@ -21,6 +21,8 @@ info = warn = None
|
|||||||
|
|
||||||
class OSX32_Freeze(Command):
|
class OSX32_Freeze(Command):
|
||||||
|
|
||||||
|
description = 'Freeze OSX calibre installation'
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
global info, warn
|
global info, warn
|
||||||
info, warn = self.info, self.warn
|
info, warn = self.info, self.warn
|
||||||
|
@ -14,6 +14,8 @@ from setup.installer.windows import build_installer
|
|||||||
|
|
||||||
class Win(Command):
|
class Win(Command):
|
||||||
|
|
||||||
|
description = 'Build windows binary installers'
|
||||||
|
|
||||||
sub_commands = ['win32']
|
sub_commands = ['win32']
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
@ -22,6 +24,8 @@ class Win(Command):
|
|||||||
|
|
||||||
class Win32(VMInstaller):
|
class Win32(VMInstaller):
|
||||||
|
|
||||||
|
description = 'Build 32bit windows binary installer'
|
||||||
|
|
||||||
INSTALLER_EXT = 'exe'
|
INSTALLER_EXT = 'exe'
|
||||||
VM_NAME = 'xp_build'
|
VM_NAME = 'xp_build'
|
||||||
VM = '/vmware/bin/%s'%VM_NAME
|
VM = '/vmware/bin/%s'%VM_NAME
|
||||||
|
@ -52,6 +52,8 @@ info = warn = None
|
|||||||
|
|
||||||
class Win32Freeze(Command):
|
class Win32Freeze(Command):
|
||||||
|
|
||||||
|
description = 'Freeze windows calibre installation'
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
global info, warn
|
global info, warn
|
||||||
info, warn = self.info, self.warn
|
info, warn = self.info, self.warn
|
||||||
|
@ -24,6 +24,8 @@ def get_opts_from_parser(parser):
|
|||||||
|
|
||||||
class Resources(Command):
|
class Resources(Command):
|
||||||
|
|
||||||
|
description = 'Compile various needed calibre resources'
|
||||||
|
|
||||||
def get_recipes(self):
|
def get_recipes(self):
|
||||||
sdir = os.path.join('src', 'calibre', 'web', 'feeds', 'recipes')
|
sdir = os.path.join('src', 'calibre', 'web', 'feeds', 'recipes')
|
||||||
resources= {}
|
resources= {}
|
||||||
|
@ -196,6 +196,7 @@ class GetTranslations(Translations):
|
|||||||
|
|
||||||
class ISO639(Command):
|
class ISO639(Command):
|
||||||
|
|
||||||
|
description = 'Compile translations for ISO 639 codes'
|
||||||
XML = '/usr/lib/python2.6/site-packages/pycountry/databases/iso639.xml'
|
XML = '/usr/lib/python2.6/site-packages/pycountry/databases/iso639.xml'
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
|
@ -127,6 +127,8 @@ class UploadDemo(Command):
|
|||||||
|
|
||||||
class UploadToServer(Command):
|
class UploadToServer(Command):
|
||||||
|
|
||||||
|
description = 'Upload miscellaneous data to calibre server'
|
||||||
|
|
||||||
def run(self, opts):
|
def run(self, opts):
|
||||||
check_call('ssh divok rm -f %s/calibre-\*.tar.gz'%DOWNLOADS, shell=True)
|
check_call('ssh divok rm -f %s/calibre-\*.tar.gz'%DOWNLOADS, shell=True)
|
||||||
check_call('scp dist/calibre-*.tar.gz divok:%s/'%DOWNLOADS, shell=True)
|
check_call('scp dist/calibre-*.tar.gz divok:%s/'%DOWNLOADS, shell=True)
|
||||||
|
@ -179,8 +179,8 @@ def main(args=sys.argv):
|
|||||||
elif opts.add_simple_plugin is not None:
|
elif opts.add_simple_plugin is not None:
|
||||||
add_simple_plugin(opts.add_simple_plugin)
|
add_simple_plugin(opts.add_simple_plugin)
|
||||||
elif opts.paths:
|
elif opts.paths:
|
||||||
prints('CALIBRE_RESOURCES_LOCATION='+sys.resources_location)
|
prints('CALIBRE_RESOURCES_PATH='+sys.resources_location)
|
||||||
prints('CALIBRE_EXTENSIONS_LOCATION='+sys.extensions_location)
|
prints('CALIBRE_EXTENSIONS_PATH='+sys.extensions_location)
|
||||||
prints('CALIBRE_PYTHON_PATH='+os.pathsep.join(sys.path))
|
prints('CALIBRE_PYTHON_PATH='+os.pathsep.join(sys.path))
|
||||||
elif opts.pdfreflow:
|
elif opts.pdfreflow:
|
||||||
from calibre.ebooks.pdf.reflow import option_parser as px, run
|
from calibre.ebooks.pdf.reflow import option_parser as px, run
|
||||||
|
@ -27,6 +27,7 @@ int get_root() {
|
|||||||
int do_mount(char *dev, char *mp) {
|
int do_mount(char *dev, char *mp) {
|
||||||
char options[1000];
|
char options[1000];
|
||||||
char marker[2000];
|
char marker[2000];
|
||||||
|
int errsv;
|
||||||
if (exists(dev) == 0) {
|
if (exists(dev) == 0) {
|
||||||
fprintf(stderr, "Specified device node does not exist\n");
|
fprintf(stderr, "Specified device node does not exist\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -55,19 +56,19 @@ int do_mount(char *dev, char *mp) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
execlp("mount", "mount", "-t", "vfat", "-o", options, dev, mp, NULL);
|
execlp("mount", "mount", "-t", "vfat", "-o", options, dev, mp, NULL);
|
||||||
int errsv = errno;
|
errsv = errno;
|
||||||
fprintf(stderr, "Failed to mount with error: %s\n", strerror(errsv));
|
fprintf(stderr, "Failed to mount with error: %s\n", strerror(errsv));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_eject(char *dev, char*mp) {
|
int do_eject(char *dev, char*mp) {
|
||||||
char marker[2000];
|
char marker[2000];
|
||||||
int status = EXIT_FAILURE, ret;
|
int status = EXIT_FAILURE, ret, pid, errsv, i, rmd;
|
||||||
if (get_root() != 0) {
|
if (get_root() != 0) {
|
||||||
fprintf(stderr, "Failed to elevate to root privileges\n");
|
fprintf(stderr, "Failed to elevate to root privileges\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
int pid = fork();
|
pid = fork();
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
fprintf(stderr, "Failed to fork\n");
|
fprintf(stderr, "Failed to fork\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -78,11 +79,10 @@ int do_eject(char *dev, char*mp) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
execlp("eject", "eject", "-s", dev, NULL);
|
execlp("eject", "eject", "-s", dev, NULL);
|
||||||
int errsv = errno;
|
errsv = errno;
|
||||||
fprintf(stderr, "Failed to eject with error: %s\n", strerror(errsv));
|
fprintf(stderr, "Failed to eject with error: %s\n", strerror(errsv));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
int i;
|
|
||||||
for (i =0; i < 7; i++) {
|
for (i =0; i < 7; i++) {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
ret = waitpid(pid, &status, WNOHANG);
|
ret = waitpid(pid, &status, WNOHANG);
|
||||||
@ -99,7 +99,7 @@ int do_eject(char *dev, char*mp) {
|
|||||||
fprintf(stderr, "Failed to unlink marker: %s\n", strerror(errno));
|
fprintf(stderr, "Failed to unlink marker: %s\n", strerror(errno));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
int rmd = rmdir(mp);
|
rmd = rmdir(mp);
|
||||||
if (rmd == -1) {
|
if (rmd == -1) {
|
||||||
fprintf(stderr, "Failed to remove mount point: %s\n", strerror(errno));
|
fprintf(stderr, "Failed to remove mount point: %s\n", strerror(errno));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
''' Post installation script for linux '''
|
''' Post installation script for linux '''
|
||||||
import sys, os, shutil
|
|
||||||
|
import sys, os, shutil, cPickle, textwrap
|
||||||
from subprocess import check_call
|
from subprocess import check_call
|
||||||
|
|
||||||
from calibre import __version__, __appname__
|
from calibre import __version__, __appname__, prints
|
||||||
from calibre.customize.ui import device_plugins
|
|
||||||
|
|
||||||
DEVICES = device_plugins()
|
|
||||||
|
|
||||||
DESTDIR = ''
|
|
||||||
if os.environ.has_key('DESTDIR'):
|
|
||||||
DESTDIR = os.environ['DESTDIR']
|
|
||||||
|
|
||||||
entry_points = {
|
entry_points = {
|
||||||
'console_scripts': [ \
|
'console_scripts': [ \
|
||||||
@ -40,6 +36,335 @@ entry_points = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNINSTALL = '''\
|
||||||
|
#!{python}
|
||||||
|
euid = {euid}
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
if os.geteuid() != euid:
|
||||||
|
print 'WARNING: uninstaller must be run as', euid, 'to remove all files'
|
||||||
|
|
||||||
|
for x in {manifest!r}:
|
||||||
|
if not os.path.exists(x): continue
|
||||||
|
try:
|
||||||
|
if os.path.isdir(x):
|
||||||
|
shutil.rmtree(x)
|
||||||
|
else:
|
||||||
|
os.unlink(x)
|
||||||
|
except Exception, e:
|
||||||
|
print 'Failed to delete', x
|
||||||
|
print '\t', e
|
||||||
|
'''
|
||||||
|
|
||||||
|
class PostInstall:
|
||||||
|
|
||||||
|
def task_failed(self, msg):
|
||||||
|
self.warn(msg, 'with error:')
|
||||||
|
import traceback
|
||||||
|
tb = '\n\t'.join(traceback.format_exc().splitlines())
|
||||||
|
self.info('\t'+tb)
|
||||||
|
print
|
||||||
|
|
||||||
|
def warning(self, *args, **kwargs):
|
||||||
|
print '\n'+'_'*20, 'WARNING','_'*20
|
||||||
|
prints(*args, **kwargs)
|
||||||
|
print '_'*50
|
||||||
|
self.warnings.append((args, kwargs))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, opts, info=prints, warn=None, manifest=None):
|
||||||
|
self.opts = opts
|
||||||
|
self.info = info
|
||||||
|
self.warn = warn
|
||||||
|
self.warnings = []
|
||||||
|
if self.warn is None:
|
||||||
|
self.warn = self.warning
|
||||||
|
|
||||||
|
if not self.opts.staging_bindir:
|
||||||
|
self.opts.staging_bindir = os.path.join(self.opts.staging_root,
|
||||||
|
'bin')
|
||||||
|
if not self.opts.staging_sharedir:
|
||||||
|
self.opts.staging_sharedir = os.path.join(self.opts.staging_root,
|
||||||
|
'etc')
|
||||||
|
self.opts.staging_etc = '/etc' if self.opts.staging_root == '/usr' else \
|
||||||
|
os.path.join(self.opts.staging_root, 'etc')
|
||||||
|
|
||||||
|
scripts = cPickle.loads(P('scripts.pickle', data=True))
|
||||||
|
if getattr(sys, 'frozen_path', False):
|
||||||
|
self.info('Creating symlinks...')
|
||||||
|
for exe in scripts.keys():
|
||||||
|
dest = os.path.join(self.opts.staging_bindir, exe)
|
||||||
|
if os.path.exists(dest):
|
||||||
|
os.unlink(dest)
|
||||||
|
tgt = os.path.join(getattr(sys, 'frozen_path'), exe)
|
||||||
|
self.info('\tSymlinking %s to %s'%(tgt, dest))
|
||||||
|
os.symlink(tgt, dest)
|
||||||
|
|
||||||
|
if manifest is None:
|
||||||
|
manifest = [os.path.abspath(os.path.join(opts.staging_bindir, x)) for x in
|
||||||
|
scripts.keys()]
|
||||||
|
self.manifest = manifest
|
||||||
|
self.icon_resources = []
|
||||||
|
self.menu_resources = []
|
||||||
|
self.mime_resources = []
|
||||||
|
self.setup_completion()
|
||||||
|
self.setup_udev_rules()
|
||||||
|
self.install_man_pages()
|
||||||
|
self.setup_desktop_integration()
|
||||||
|
|
||||||
|
from calibre.utils.config import config_dir
|
||||||
|
if os.path.exists(config_dir):
|
||||||
|
os.chdir(config_dir)
|
||||||
|
for f in os.listdir('.'):
|
||||||
|
if os.stat(f).st_uid == 0:
|
||||||
|
os.rmdir(f) if os.path.isdir(f) else os.unlink(f)
|
||||||
|
if os.stat(config_dir).st_uid == 0:
|
||||||
|
os.rmdir(config_dir)
|
||||||
|
|
||||||
|
if warn is None and self.warnings:
|
||||||
|
self.info('There were %d warnings'%len(self.warnings))
|
||||||
|
for args, kwargs in self.warnings:
|
||||||
|
self.info('*', *args, **kwargs)
|
||||||
|
print
|
||||||
|
|
||||||
|
|
||||||
|
def setup_completion(self):
|
||||||
|
try:
|
||||||
|
self.info('Setting up bash completion...')
|
||||||
|
from calibre.ebooks.metadata.cli import option_parser as metaop, filetypes as meta_filetypes
|
||||||
|
from calibre.ebooks.lrf.lrfparser import option_parser as lrf2lrsop
|
||||||
|
from calibre.gui2.lrf_renderer.main import option_parser as lrfviewerop
|
||||||
|
from calibre.web.fetch.simple import option_parser as web2disk
|
||||||
|
from calibre.web.feeds.recipes import titles as feed_titles
|
||||||
|
from calibre.ebooks.metadata.fetch import option_parser as fem_op
|
||||||
|
from calibre.gui2.main import option_parser as guiop
|
||||||
|
from calibre.utils.smtp import option_parser as smtp_op
|
||||||
|
any_formats = ['epub', 'htm', 'html', 'xhtml', 'xhtm', 'rar', 'zip',
|
||||||
|
'txt', 'lit', 'rtf', 'pdf', 'prc', 'mobi', 'fb2', 'odt']
|
||||||
|
if os.path.exists(os.path.join(self.opts.staging_sharedir,
|
||||||
|
'bash-completion')):
|
||||||
|
f = os.path.join(self.opts.staging_sharedir,
|
||||||
|
'bash-completion', 'calibre')
|
||||||
|
else:
|
||||||
|
f = os.path.join(self.opts.staging_etc,
|
||||||
|
'bash_completion.d/calibre')
|
||||||
|
if not os.path.exists(os.path.dirname(f)):
|
||||||
|
os.makedirs(os.path.dirname(f))
|
||||||
|
self.manifest.append(f)
|
||||||
|
with open(f, 'wb') as f:
|
||||||
|
f.write('# calibre Bash Shell Completion\n')
|
||||||
|
f.write(opts_and_exts('calibre', guiop, any_formats))
|
||||||
|
f.write(opts_and_exts('lrf2lrs', lrf2lrsop, ['lrf']))
|
||||||
|
f.write(opts_and_exts('ebook-meta', metaop, list(meta_filetypes())))
|
||||||
|
f.write(opts_and_exts('lrfviewer', lrfviewerop, ['lrf']))
|
||||||
|
f.write(opts_and_words('web2disk', web2disk, feed_titles))
|
||||||
|
f.write(opts_and_words('fetch-ebook-metadata', fem_op, []))
|
||||||
|
f.write(opts_and_words('calibre-smtp', smtp_op, []))
|
||||||
|
f.write(textwrap.dedent('''
|
||||||
|
_ebook_device_ls()
|
||||||
|
{
|
||||||
|
local pattern search listing prefix
|
||||||
|
pattern="$1"
|
||||||
|
search="$1"
|
||||||
|
if [[ -n "{$pattern}" ]]; then
|
||||||
|
if [[ "${pattern:(-1)}" == "/" ]]; then
|
||||||
|
pattern=""
|
||||||
|
else
|
||||||
|
pattern="$(basename ${pattern} 2> /dev/null)"
|
||||||
|
search="$(dirname ${search} 2> /dev/null)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "x${search}" == "x" || "x${search}" == "x." ]]; then
|
||||||
|
search="/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
listing="$(ebook-device ls ${search} 2>/dev/null)"
|
||||||
|
|
||||||
|
prefix="${search}"
|
||||||
|
if [[ "x${prefix:(-1)}" != "x/" ]]; then
|
||||||
|
prefix="${prefix}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}")
|
||||||
|
}
|
||||||
|
|
||||||
|
_ebook_device()
|
||||||
|
{
|
||||||
|
local cur prev
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
COMPREPLY=()
|
||||||
|
case "${prev}" in
|
||||||
|
ls|rm|mkdir|touch|cat )
|
||||||
|
COMPREPLY=( $(_ebook_device_ls "${cur}") )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
cp )
|
||||||
|
if [[ ${cur} == prs500:* ]]; then
|
||||||
|
COMPREPLY=( $(_ebook_device_ls "${cur:7}") )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_filedir
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
prs500 )
|
||||||
|
COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
if [[ ${cur} == prs500:* ]]; then
|
||||||
|
COMPREPLY=( $(_ebook_device_ls "${cur:7}") )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
if [[ ${prev} == prs500:* ]]; then
|
||||||
|
_filedir
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "prs500:" "${cur}") )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
complete -o nospace -F _ebook_device ebook-device
|
||||||
|
|
||||||
|
complete -o nospace -C calibre-complete ebook-convert
|
||||||
|
'''))
|
||||||
|
except TypeError, err:
|
||||||
|
if 'resolve_entities' in str(err):
|
||||||
|
print 'You need python-lxml >= 2.0.5 for calibre'
|
||||||
|
sys.exit(1)
|
||||||
|
raise
|
||||||
|
except:
|
||||||
|
if self.opts.fatal_errors:
|
||||||
|
raise
|
||||||
|
self.task_failed('Setting up completion failed')
|
||||||
|
|
||||||
|
def setup_udev_rules(self):
|
||||||
|
self.info('Trying to setup udev rules...')
|
||||||
|
try:
|
||||||
|
group_file = os.path.join(self.opts.staging_etc, 'group')
|
||||||
|
groups = open(group_file, 'rb').read()
|
||||||
|
group = 'plugdev' if 'plugdev' in groups else 'usb'
|
||||||
|
old_udev = '/etc/udev/rules.d/95-calibre.rules'
|
||||||
|
if os.path.exists(old_udev):
|
||||||
|
os.remove(old_udev)
|
||||||
|
if self.opts.staging_root == '/usr':
|
||||||
|
base = '/lib'
|
||||||
|
else:
|
||||||
|
base = os.path.join(self.opts.staging_root, 'lib')
|
||||||
|
base = os.path.join(base, 'udev', 'rules.d')
|
||||||
|
if not os.path.exists(base):
|
||||||
|
os.makedirs(base)
|
||||||
|
with open(os.path.join(base, '95-calibre.rules'), 'wb') as udev:
|
||||||
|
self.manifest.append(udev.name)
|
||||||
|
udev.write('''# Sony Reader PRS-500\n'''
|
||||||
|
'''BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="%s"\n'''%(group,)
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
if self.opts.fatal_errors:
|
||||||
|
raise
|
||||||
|
self.task_failed('Setting up udev rules failed')
|
||||||
|
|
||||||
|
def install_man_pages(self):
|
||||||
|
try:
|
||||||
|
from calibre.utils.help2man import create_man_page
|
||||||
|
manpath = os.path.join(self.opts.staging_sharedir, 'man/man1')
|
||||||
|
if not os.path.exists(manpath):
|
||||||
|
os.makedirs(manpath)
|
||||||
|
self.info('Installing MAN pages...')
|
||||||
|
for src in entry_points['console_scripts']:
|
||||||
|
prog, right = src.split('=')
|
||||||
|
prog = prog.strip()
|
||||||
|
module = __import__(right.split(':')[0].strip(), fromlist=['a'])
|
||||||
|
parser = getattr(module, 'option_parser', None)
|
||||||
|
if parser is None:
|
||||||
|
continue
|
||||||
|
parser = parser()
|
||||||
|
raw = create_man_page(prog, parser)
|
||||||
|
manfile = os.path.join(manpath, prog+'.1'+__appname__+'.bz2')
|
||||||
|
self.info('\tInstalling MAN page for', prog)
|
||||||
|
open(manfile, 'wb').write(raw)
|
||||||
|
self.manifest.append(manfile)
|
||||||
|
except:
|
||||||
|
if self.opts.fatal_errors:
|
||||||
|
raise
|
||||||
|
self.task_failed('Installing MAN pages failed')
|
||||||
|
|
||||||
|
def setup_desktop_integration(self):
|
||||||
|
try:
|
||||||
|
from PyQt4.QtCore import QFile
|
||||||
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
|
self.info('Setting up desktop integration...')
|
||||||
|
|
||||||
|
|
||||||
|
tdir = mkdtemp()
|
||||||
|
cwd = os.getcwdu()
|
||||||
|
try:
|
||||||
|
os.chdir(tdir)
|
||||||
|
render_svg(QFile(I('mimetypes/lrf.svg')), os.path.join(tdir, 'calibre-lrf.png'))
|
||||||
|
check_call('xdg-icon-resource install --noupdate --context mimetypes --size 128 calibre-lrf.png application-lrf', shell=True)
|
||||||
|
self.icon_resources.append(('mimetypes', 'application-lrf'))
|
||||||
|
check_call('xdg-icon-resource install --noupdate --context mimetypes --size 128 calibre-lrf.png text-lrs', shell=True)
|
||||||
|
self.icon_resources.append(('mimetypes', 'application-lrs'))
|
||||||
|
QFile(I('library.png')).copy(os.path.join(tdir, 'calibre-gui.png'))
|
||||||
|
check_call('xdg-icon-resource install --noupdate --size 128 calibre-gui.png calibre-gui', shell=True)
|
||||||
|
self.icon_resources.append(('apps', 'calibre-gui'))
|
||||||
|
render_svg(QFile(I('viewer.svg')), os.path.join(tdir, 'calibre-viewer.png'))
|
||||||
|
check_call('xdg-icon-resource install --size 128 calibre-viewer.png calibre-viewer', shell=True)
|
||||||
|
self.icon_resources.append(('apps', 'calibre-viewer'))
|
||||||
|
|
||||||
|
f = open('calibre-lrfviewer.desktop', 'wb')
|
||||||
|
f.write(VIEWER)
|
||||||
|
f.close()
|
||||||
|
f = open('calibre-ebook-viewer.desktop', 'wb')
|
||||||
|
f.write(EVIEWER)
|
||||||
|
f.close()
|
||||||
|
f = open('calibre-gui.desktop', 'wb')
|
||||||
|
f.write(GUI)
|
||||||
|
f.close()
|
||||||
|
des = ('calibre-gui.desktop', 'calibre-lrfviewer.desktop',
|
||||||
|
'calibre-ebook-viewer.desktop')
|
||||||
|
for x in des:
|
||||||
|
cmd = ['xdg-desktop-menu', 'install', './'+x]
|
||||||
|
if x != des[-1]:
|
||||||
|
cmd.insert(2, '--noupdate')
|
||||||
|
check_call(' '.join(cmd), shell=True)
|
||||||
|
self.menu_resources.append(x)
|
||||||
|
f = open('calibre-mimetypes', 'wb')
|
||||||
|
f.write(MIME)
|
||||||
|
f.close()
|
||||||
|
self.mime_resources.append('calibre-mimetypes')
|
||||||
|
check_call('xdg-mime install ./calibre-mimetypes', shell=True)
|
||||||
|
finally:
|
||||||
|
os.chdir(cwd)
|
||||||
|
shutil.rmtree(tdir)
|
||||||
|
except Exception, err:
|
||||||
|
if self.opts.fatal_errors:
|
||||||
|
raise
|
||||||
|
self.task_failed('Setting up desktop integration failed')
|
||||||
|
|
||||||
|
def option_parser():
|
||||||
|
from calibre.utils.config import OptionParser
|
||||||
|
parser = OptionParser()
|
||||||
|
parser.add_option('--make-errors-fatal', action='store_true', default=False,
|
||||||
|
dest='fatal_errors', help='If set die on errors.')
|
||||||
|
parser.add_option('--root', dest='staging_root', default='/usr',
|
||||||
|
help='Prefix under which to install files')
|
||||||
|
parser.add_option('--bindir', default=None, dest='staging_bindir',
|
||||||
|
help='Location where calibre launcher scripts were installed')
|
||||||
|
parser.add_option('--sharedir', default=None, dest='staging_sharedir',
|
||||||
|
help='Location where calibre resources were installed')
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def options(option_parser):
|
def options(option_parser):
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
@ -121,194 +446,6 @@ def opts_and_exts(name, op, exts):
|
|||||||
}
|
}
|
||||||
complete -o filenames -F _'''%(opts,exts) + name + ' ' + name +"\n\n"
|
complete -o filenames -F _'''%(opts,exts) + name + ' ' + name +"\n\n"
|
||||||
|
|
||||||
use_destdir = False
|
|
||||||
|
|
||||||
def open_file(path, mode='wb'):
|
|
||||||
if use_destdir:
|
|
||||||
if os.path.isabs(path):
|
|
||||||
path = path[1:]
|
|
||||||
path = os.path.join(DESTDIR, path)
|
|
||||||
if not os.path.exists(os.path.dirname(path)):
|
|
||||||
os.makedirs(os.path.dirname(path))
|
|
||||||
return open(path, mode)
|
|
||||||
|
|
||||||
def setup_completion(fatal_errors):
|
|
||||||
manifest = []
|
|
||||||
try:
|
|
||||||
print 'Setting up bash completion...',
|
|
||||||
sys.stdout.flush()
|
|
||||||
from calibre.ebooks.metadata.cli import option_parser as metaop, filetypes as meta_filetypes
|
|
||||||
from calibre.ebooks.lrf.lrfparser import option_parser as lrf2lrsop
|
|
||||||
from calibre.gui2.lrf_renderer.main import option_parser as lrfviewerop
|
|
||||||
from calibre.web.fetch.simple import option_parser as web2disk
|
|
||||||
from calibre.web.feeds.recipes import titles as feed_titles
|
|
||||||
from calibre.ebooks.metadata.fetch import option_parser as fem_op
|
|
||||||
from calibre.gui2.main import option_parser as guiop
|
|
||||||
from calibre.utils.smtp import option_parser as smtp_op
|
|
||||||
any_formats = ['epub', 'htm', 'html', 'xhtml', 'xhtm', 'rar', 'zip',
|
|
||||||
'txt', 'lit', 'rtf', 'pdf', 'prc', 'mobi', 'fb2', 'odt']
|
|
||||||
if os.path.exists('/usr/share/bash-completion'):
|
|
||||||
f = open_file('/usr/share/bash-completion/calibre')
|
|
||||||
else:
|
|
||||||
f = open_file('/etc/bash_completion.d/calibre')
|
|
||||||
manifest.append(f.name)
|
|
||||||
|
|
||||||
f.write('# calibre Bash Shell Completion\n')
|
|
||||||
f.write(opts_and_exts('calibre', guiop, any_formats))
|
|
||||||
f.write(opts_and_exts('lrf2lrs', lrf2lrsop, ['lrf']))
|
|
||||||
f.write(opts_and_exts('ebook-meta', metaop, list(meta_filetypes())))
|
|
||||||
f.write(opts_and_exts('lrfviewer', lrfviewerop, ['lrf']))
|
|
||||||
f.write(opts_and_words('web2disk', web2disk, feed_titles))
|
|
||||||
f.write(opts_and_words('fetch-ebook-metadata', fem_op, []))
|
|
||||||
f.write(opts_and_words('calibre-smtp', smtp_op, []))
|
|
||||||
f.write('''
|
|
||||||
_prs500_ls()
|
|
||||||
{
|
|
||||||
local pattern search listing prefix
|
|
||||||
pattern="$1"
|
|
||||||
search="$1"
|
|
||||||
if [[ -n "{$pattern}" ]]; then
|
|
||||||
if [[ "${pattern:(-1)}" == "/" ]]; then
|
|
||||||
pattern=""
|
|
||||||
else
|
|
||||||
pattern="$(basename ${pattern} 2> /dev/null)"
|
|
||||||
search="$(dirname ${search} 2> /dev/null)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "x${search}" == "x" || "x${search}" == "x." ]]; then
|
|
||||||
search="/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
listing="$(prs500 ls ${search} 2>/dev/null)"
|
|
||||||
|
|
||||||
prefix="${search}"
|
|
||||||
if [[ "x${prefix:(-1)}" != "x/" ]]; then
|
|
||||||
prefix="${prefix}/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}")
|
|
||||||
}
|
|
||||||
|
|
||||||
_prs500()
|
|
||||||
{
|
|
||||||
local cur prev
|
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
COMPREPLY=()
|
|
||||||
case "${prev}" in
|
|
||||||
ls|rm|mkdir|touch|cat )
|
|
||||||
COMPREPLY=( $(_prs500_ls "${cur}") )
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
cp )
|
|
||||||
if [[ ${cur} == prs500:* ]]; then
|
|
||||||
COMPREPLY=( $(_prs500_ls "${cur:7}") )
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_filedir
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
prs500 )
|
|
||||||
COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") )
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
if [[ ${cur} == prs500:* ]]; then
|
|
||||||
COMPREPLY=( $(_prs500_ls "${cur:7}") )
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
if [[ ${prev} == prs500:* ]]; then
|
|
||||||
_filedir
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
COMPREPLY=( $(compgen -W "prs500:" "${cur}") )
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
complete -o nospace -F _prs500 ebook-device
|
|
||||||
|
|
||||||
complete -o nospace -C calibre-complete ebook-convert
|
|
||||||
''')
|
|
||||||
f.close()
|
|
||||||
print 'done'
|
|
||||||
except TypeError, err:
|
|
||||||
if 'resolve_entities' in str(err):
|
|
||||||
print 'You need python-lxml >= 2.0.5 for calibre'
|
|
||||||
sys.exit(1)
|
|
||||||
raise
|
|
||||||
except:
|
|
||||||
if fatal_errors:
|
|
||||||
raise
|
|
||||||
print 'failed'
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def setup_udev_rules(group_file, reload, fatal_errors):
|
|
||||||
print 'Trying to setup udev rules...'
|
|
||||||
manifest = []
|
|
||||||
sys.stdout.flush()
|
|
||||||
groups = open(group_file, 'rb').read()
|
|
||||||
group = 'plugdev' if 'plugdev' in groups else 'usb'
|
|
||||||
old_udev = '/etc/udev/rules.d/95-calibre.rules'
|
|
||||||
if os.path.exists(old_udev):
|
|
||||||
os.remove(old_udev)
|
|
||||||
if os.path.exists('/lib/udev/rules.d'):
|
|
||||||
udev = open_file('/lib/udev/rules.d/95-calibre.rules')
|
|
||||||
else:
|
|
||||||
udev = open_file(old_udev)
|
|
||||||
manifest.append(udev.name)
|
|
||||||
udev.write('''# Sony Reader PRS-500\n'''
|
|
||||||
'''BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="%s"\n'''%(group,)
|
|
||||||
)
|
|
||||||
udev.close()
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def option_parser():
|
|
||||||
from optparse import OptionParser
|
|
||||||
parser = OptionParser()
|
|
||||||
parser.add_option('--use-destdir', action='store_true', default=False, dest='destdir',
|
|
||||||
help='If set, respect the environment variable DESTDIR when installing files')
|
|
||||||
parser.add_option('--do-not-reload-udev-hal', action='store_true', dest='dont_reload', default=False,
|
|
||||||
help='Does nothing. Present for legacy reasons.')
|
|
||||||
parser.add_option('--group-file', default='/etc/group', dest='group_file',
|
|
||||||
help='File from which to read group information. Default: %default')
|
|
||||||
parser.add_option('--dont-check-root', action='store_true', default=False, dest='no_root',
|
|
||||||
help='If set, do not check if we are root.')
|
|
||||||
parser.add_option('--make-errors-fatal', action='store_true', default=False,
|
|
||||||
dest='fatal_errors', help='If set die on errors.')
|
|
||||||
parser.add_option('--save-manifest-to', default=None,
|
|
||||||
help='Save a manifest of all installed files to the specified location')
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def install_man_pages(fatal_errors, use_destdir=False):
|
|
||||||
from calibre.utils.help2man import create_man_page
|
|
||||||
prefix = os.environ.get('DESTDIR', '/') if use_destdir else '/'
|
|
||||||
manpath = os.path.join(prefix, 'usr/share/man/man1')
|
|
||||||
if not os.path.exists(manpath):
|
|
||||||
os.makedirs(manpath)
|
|
||||||
print 'Installing MAN pages...'
|
|
||||||
manifest = []
|
|
||||||
for src in entry_points['console_scripts']:
|
|
||||||
prog, right = src.split('=')
|
|
||||||
prog = prog.strip()
|
|
||||||
module = __import__(right.split(':')[0].strip(), fromlist=['a'])
|
|
||||||
parser = getattr(module, 'option_parser', None)
|
|
||||||
if parser is None:
|
|
||||||
continue
|
|
||||||
parser = parser()
|
|
||||||
raw = create_man_page(prog, parser)
|
|
||||||
manfile = os.path.join(manpath, prog+'.1'+__appname__+'.bz2')
|
|
||||||
print '\tInstalling MAN page for', prog
|
|
||||||
open(manfile, 'wb').write(raw)
|
|
||||||
manifest.append(manfile)
|
|
||||||
return manifest
|
|
||||||
|
|
||||||
def post_install():
|
def post_install():
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
@ -317,13 +454,6 @@ def post_install():
|
|||||||
global use_destdir
|
global use_destdir
|
||||||
use_destdir = opts.destdir
|
use_destdir = opts.destdir
|
||||||
manifest = []
|
manifest = []
|
||||||
setup_desktop_integration(opts.fatal_errors)
|
|
||||||
if opts.no_root or os.geteuid() == 0:
|
|
||||||
manifest += install_man_pages(opts.fatal_errors, use_destdir)
|
|
||||||
manifest += setup_udev_rules(opts.group_file, not opts.dont_reload, opts.fatal_errors)
|
|
||||||
manifest += setup_completion(opts.fatal_errors)
|
|
||||||
else:
|
|
||||||
print "Skipping udev, completion, and man-page install for non-root user."
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PyQt4 import Qt
|
from PyQt4 import Qt
|
||||||
@ -335,26 +465,9 @@ def post_install():
|
|||||||
if opts.save_manifest_to:
|
if opts.save_manifest_to:
|
||||||
open(opts.save_manifest_to, 'wb').write('\n'.join(manifest)+'\n')
|
open(opts.save_manifest_to, 'wb').write('\n'.join(manifest)+'\n')
|
||||||
|
|
||||||
from calibre.utils.config import config_dir
|
|
||||||
if os.path.exists(config_dir):
|
|
||||||
os.chdir(config_dir)
|
|
||||||
for f in os.listdir('.'):
|
|
||||||
if os.stat(f).st_uid == 0:
|
|
||||||
os.rmdir(f) if os.path.isdir(f) else os.unlink(f)
|
|
||||||
if os.stat(config_dir).st_uid == 0:
|
|
||||||
os.rmdir(config_dir)
|
|
||||||
|
|
||||||
def binary_install():
|
def binary_install():
|
||||||
manifest = os.path.join(getattr(sys, 'frozen_path'), 'manifest')
|
manifest = os.path.join(getattr(sys, 'frozen_path'), 'manifest')
|
||||||
exes = [x.strip() for x in open(manifest).readlines()]
|
|
||||||
print 'Creating symlinks...'
|
|
||||||
for exe in exes:
|
|
||||||
dest = os.path.join('/usr', 'bin', exe)
|
|
||||||
if os.path.exists(dest):
|
|
||||||
os.unlink(dest)
|
|
||||||
tgt = os.path.join(getattr(sys, 'frozen_path'), exe)
|
|
||||||
print '\tSymlinking %s to %s'%(tgt, dest)
|
|
||||||
os.symlink(tgt, dest)
|
|
||||||
post_install()
|
post_install()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@ -431,50 +544,12 @@ def render_svg(image, dest):
|
|||||||
painter.end()
|
painter.end()
|
||||||
image.save(dest)
|
image.save(dest)
|
||||||
|
|
||||||
def setup_desktop_integration(fatal_errors):
|
def main():
|
||||||
try:
|
p = option_parser()
|
||||||
from PyQt4.QtCore import QFile
|
opts, args = p.parse_args()
|
||||||
from tempfile import mkdtemp
|
PostInstall(opts)
|
||||||
|
return 0
|
||||||
print 'Setting up desktop integration...'
|
|
||||||
|
|
||||||
|
|
||||||
tdir = mkdtemp()
|
|
||||||
cwd = os.getcwdu()
|
|
||||||
try:
|
|
||||||
os.chdir(tdir)
|
|
||||||
render_svg(QFile(I('mimetypes/lrf.svg')), os.path.join(tdir, 'calibre-lrf.png'))
|
|
||||||
check_call('xdg-icon-resource install --context mimetypes --size 128 calibre-lrf.png application-lrf', shell=True)
|
|
||||||
check_call('xdg-icon-resource install --context mimetypes --size 128 calibre-lrf.png text-lrs', shell=True)
|
|
||||||
QFile(I('library.png')).copy(os.path.join(tdir, 'calibre-gui.png'))
|
|
||||||
check_call('xdg-icon-resource install --size 128 calibre-gui.png calibre-gui', shell=True)
|
|
||||||
render_svg(QFile(I('viewer.svg')), os.path.join(tdir, 'calibre-viewer.png'))
|
|
||||||
check_call('xdg-icon-resource install --size 128 calibre-viewer.png calibre-viewer', shell=True)
|
|
||||||
|
|
||||||
f = open('calibre-lrfviewer.desktop', 'wb')
|
|
||||||
f.write(VIEWER)
|
|
||||||
f.close()
|
|
||||||
f = open('calibre-ebook-viewer.desktop', 'wb')
|
|
||||||
f.write(EVIEWER)
|
|
||||||
f.close()
|
|
||||||
f = open('calibre-gui.desktop', 'wb')
|
|
||||||
f.write(GUI)
|
|
||||||
f.close()
|
|
||||||
check_call('xdg-desktop-menu install ./calibre-gui.desktop ./calibre-lrfviewer.desktop', shell=True)
|
|
||||||
f = open('calibre-mimetypes', 'wb')
|
|
||||||
f.write(MIME)
|
|
||||||
f.close()
|
|
||||||
check_call('xdg-mime install calibre-mimetypes', shell=True)
|
|
||||||
finally:
|
|
||||||
os.chdir(cwd)
|
|
||||||
shutil.rmtree(tdir)
|
|
||||||
except Exception, err:
|
|
||||||
if fatal_errors:
|
|
||||||
raise
|
|
||||||
print >>sys.stderr, 'Could not setup desktop integration. Error:'
|
|
||||||
print err
|
|
||||||
|
|
||||||
main = post_install
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
post_install()
|
sys.exit(main())
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user