diff --git a/setup/installer/__init__.py b/setup/installer/__init__.py index b976c4d448..23c68b7b8c 100644 --- a/setup/installer/__init__.py +++ b/setup/installer/__init__.py @@ -11,7 +11,7 @@ import subprocess, tempfile, os, time from setup import Command, installer_name from setup.build_environment import HOST, PROJECT -BASE_RSYNC = 'rsync -avz --delete'.split() +BASE_RSYNC = ['rsync', '-e', 'ssh -x', '-avz', '--delete'] EXCLUDES = [] for x in [ 'src/calibre/plugins', 'src/calibre/manual', 'src/calibre/trac', diff --git a/src/calibre/ebooks/metadata/toc.py b/src/calibre/ebooks/metadata/toc.py index 0ed527d26a..10d45186de 100644 --- a/src/calibre/ebooks/metadata/toc.py +++ b/src/calibre/ebooks/metadata/toc.py @@ -182,6 +182,7 @@ class TOC(list): except: play_order = 1 href = fragment = text = None + nd = dest nl = nl_path(np) if nl: nl = nl[0] @@ -190,17 +191,14 @@ class TOC(list): text += etree.tostring(txt, method='text', encoding=unicode, with_tail=False) content = content_path(np) - if not content or not text: - return - content = content[0] - src = get_attr(content, attr='src') - if src is None: - return - - purl = urlparse(unquote(content.get('src'))) - href, fragment = purl[2], purl[5] - nd = dest.add_item(href, fragment, text) - nd.play_order = play_order + if content and text: + content = content[0] + src = get_attr(content, attr='src') + if src: + purl = urlparse(unquote(content.get('src'))) + href, fragment = purl[2], purl[5] + nd = dest.add_item(href, fragment, text) + nd.play_order = play_order for c in np_path(np): process_navpoint(c, nd) diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index c46d77cd06..a1f6a6ba90 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -192,14 +192,15 @@ class EditMetadataAction(InterfaceAction): _('At least two books must be selected for merging'), show=True) dest_id, src_books, src_ids = self.books_to_merge(rows) + title = self.gui.library_view.model().db.title(dest_id, index_is_id=True) if safe_merge: if not confirm('

'+_( 'Book formats and metadata from the selected books ' - 'will be added to the first selected book. ' + 'will be added to the first selected book (%s). ' 'ISBN will not be merged.

' 'The second and subsequently selected books will not ' 'be deleted or changed.

' - 'Please confirm you want to proceed.') + 'Please confirm you want to proceed.')%title +'

', 'merge_books_safe', self.gui): return self.add_formats(dest_id, src_books) @@ -207,14 +208,14 @@ class EditMetadataAction(InterfaceAction): else: if not confirm('

'+_( 'Book formats and metadata from the selected books will be merged ' - 'into the first selected book. ' + 'into the first selected book (%s). ' 'ISBN will not be merged.

' 'After merger the second and ' 'subsequently selected books will be deleted.

' 'All book formats of the first selected book will be kept ' 'and any duplicate formats in the second and subsequently selected books ' 'will be permanently deleted from your computer.

' - 'Are you sure you want to proceed?') + 'Are you sure you want to proceed?')%title +'

', 'merge_books', self.gui): return if len(rows)>5: diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 09019af18b..4a098785b1 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -358,10 +358,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def toc_clicked(self, index): item = self.toc_model.itemFromIndex(index) - url = QUrl.fromLocalFile(item.abspath) - if item.fragment: - url.setFragment(item.fragment) - self.link_clicked(url) + if item.abspath is not None: + url = QUrl.fromLocalFile(item.abspath) + if item.fragment: + url.setFragment(item.fragment) + self.link_clicked(url) def selection_changed(self, selected_text): self.selected_text = selected_text.strip() diff --git a/src/calibre/library/server/main.py b/src/calibre/library/server/main.py index b7cb3ecf12..e4de710c6a 100644 --- a/src/calibre/library/server/main.py +++ b/src/calibre/library/server/main.py @@ -5,7 +5,7 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import sys +import sys, os from threading import Thread from calibre.library.server import server_config as config @@ -63,15 +63,47 @@ The OPDS interface is advertised via BonJour automatically. ' work in all environments.')) return parser +def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) + sys.exit(1) + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) + sys.exit(1) + + # Redirect standard file descriptors. + si = file(stdin, 'r') + so = file(stdout, 'a+') + se = file(stderr, 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + + def main(args=sys.argv): from calibre.library.database2 import LibraryDatabase2 parser = option_parser() opts, args = parser.parse_args(args) if opts.daemonize and not iswindows: - from cherrypy.process.plugins import Daemonizer - d = Daemonizer(cherrypy.engine) - d.subscribe() + daemonize() if opts.pidfile is not None: from cherrypy.process.plugins import PIDFile PIDFile(cherrypy.engine, opts.pidfile).subscribe()