Create restore command for calibredb

This commit is contained in:
Kovid Goyal 2010-09-25 21:22:59 -06:00
parent 02ce96cd68
commit 42ec47607c
2 changed files with 62 additions and 8 deletions

View File

@ -877,8 +877,54 @@ def command_saved_searches(args, dbpath):
COMMANDS = ('list', 'add', 'remove', 'add_format', 'remove_format', COMMANDS = ('list', 'add', 'remove', 'add_format', 'remove_format',
'show_metadata', 'set_metadata', 'export', 'catalog', 'show_metadata', 'set_metadata', 'export', 'catalog',
'saved_searches', 'add_custom_column', 'custom_columns', 'saved_searches', 'add_custom_column', 'custom_columns',
'remove_custom_column', 'set_custom') 'remove_custom_column', 'set_custom', 'restore_database')
def restore_database_option_parser():
parser = get_parser(_(
'''
%prog restore_database [options]
Restore this database from the metadata stored in OPF
files in each directory of the calibre library. This is
useful if your metadata.db file has been corrupted.
WARNING: This completely regenrates your datbase. You will
lose stored per-book conversion settings and custom recipes.
'''))
return parser
def command_restore_database(args, dbpath):
from calibre.library.restore import Restore
parser = saved_searches_option_parser()
opts, args = parser.parse_args(args)
if len(args) != 0:
parser.print_help()
return 1
class Progress(object):
def __init__(self): self.total = 1
def __call__(self, msg, step):
if msg is None:
self.total = float(step)
else:
prints(msg, '...', '%d%%'%int(100*(step/self.total)))
r = Restore(dbpath, progress_callback=Progress())
r.start()
r.join()
if r.tb is not None:
prints('Restoring database failed with error:')
prints(r.tb)
else:
prints('Restoring database succeeded')
if r.errors_occurred:
name = 'calibre_db_restore_report.txt'
open('calibre_db_restore_report.txt',
'wb').write(r.report.encode('utf-8'))
prints('Some errors occurred. A detailed report was '
'saved to', name)
send_message()
def option_parser(): def option_parser():
parser = OptionParser(_( parser = OptionParser(_(

View File

@ -23,12 +23,16 @@ NON_EBOOK_EXTENSIONS = frozenset([
class RestoreDatabase(LibraryDatabase2): class RestoreDatabase(LibraryDatabase2):
def set_path(self, book_id, *args, **kwargs): def set_path(self, *args, **kwargs):
pass
def dirtied(self, *args, **kwargs):
pass pass
class Restore(Thread): class Restore(Thread):
def __init__(self, library_path, progress_callback=None): def __init__(self, library_path, progress_callback=None):
super(Restore, self).__init__()
if isbytestring(library_path): if isbytestring(library_path):
library_path = library_path.decode(filesystem_encoding) library_path = library_path.decode(filesystem_encoding)
self.src_library_path = os.path.abspath(library_path) self.src_library_path = os.path.abspath(library_path)
@ -43,6 +47,7 @@ class Restore(Thread):
self.books = [] self.books = []
self.conflicting_custom_cols = {} self.conflicting_custom_cols = {}
self.failed_restores = [] self.failed_restores = []
self.tb = None
@property @property
def errors_occurred(self): def errors_occurred(self):
@ -72,12 +77,15 @@ class Restore(Thread):
def run(self): def run(self):
with TemporaryDirectory('_library_restore') as tdir: try:
self.library_path = tdir with TemporaryDirectory('_library_restore') as tdir:
self.scan_library() self.library_path = tdir
self.create_cc_metadata() self.scan_library()
self.restore_books() self.create_cc_metadata()
self.replace_db() self.restore_books()
self.replace_db()
except:
self.tb = traceback.format_exc()
def scan_library(self): def scan_library(self):
for dirpath, dirnames, filenames in os.walk(self.src_library_path): for dirpath, dirnames, filenames in os.walk(self.src_library_path):