diff --git a/src/calibre/gui2/dialogs/check_library.py b/src/calibre/gui2/dialogs/check_library.py index 8eeeda117d..177e12db49 100644 --- a/src/calibre/gui2/dialogs/check_library.py +++ b/src/calibre/gui2/dialogs/check_library.py @@ -6,7 +6,7 @@ __license__ = 'GPL v3' from PyQt4.Qt import QDialog, QVBoxLayout, QTreeWidget, QPushButton, \ QDialogButtonBox, QApplication, QTreeWidgetItem -from calibre.library.check_library import CheckLibrary +from calibre.library.check_library import CheckLibrary, CHECKS class Item(QTreeWidgetItem): pass @@ -71,7 +71,7 @@ class CheckLibraryDialog(QDialog): t.clear() t.setColumnCount(3); t.setHeaderLabels([_('Name'), _('Path from library'), _('Additional Information')]) - for check in checker.checks: + for check in CHECKS: builder(t, checker, check) t.setColumnWidth(0, 200) diff --git a/src/calibre/library/check_library.py b/src/calibre/library/check_library.py index d746018c85..ec45b49f0a 100644 --- a/src/calibre/library/check_library.py +++ b/src/calibre/library/check_library.py @@ -15,17 +15,18 @@ EBOOK_EXTENSIONS = frozenset(BOOK_EXTENSIONS) NORMALS = frozenset(['metadata.opf', 'cover.jpg']) -class CheckLibrary(object): +CHECKS = [('invalid_titles', _('Invalid titles')), + ('extra_titles', _('Extra titles')), + ('invalid_authors', _('Invalid authors')), + ('extra_authors', _('Extra authors')), + ('missing_formats', _('Missing book formats')), + ('extra_formats', _('Extra book formats')), + ('extra_files', _('Unknown files in book')), + ('failed_folders', _('Folders raising exception')) + ] - checks = [('invalid_titles', _('Invalid titles')), - ('extra_titles', _('Extra titles')), - ('invalid_authors', _('Invalid authors')), - ('extra_authors', _('Extra authors')), - ('missing_formats', _('Missing book formats')), - ('extra_formats', _('Extra book formats')), - ('extra_files', _('Unknown files in book')), - ('failed_folders', _('Folders raising exception')) - ] + +class CheckLibrary(object): def __init__(self, library_path, db): if isbytestring(library_path): @@ -35,7 +36,10 @@ class CheckLibrary(object): self.all_authors = frozenset([x[1] for x in db.all_authors()]) self.all_ids = frozenset([id for id in db.all_ids()]) + self.is_case_sensitive = db.is_case_sensitive self.all_dbpaths = frozenset(self.dbpath(id) for id in self.all_ids) + self.all_lc_dbpaths = frozenset(self.dbpath(id).lower() + for id in self.all_ids) self.db_id_regexp = re.compile(r'^.* \((\d+)\)$') self.bad_ext_pat = re.compile(r'[^a-z]+') @@ -55,13 +59,6 @@ class CheckLibrary(object): self.extra_formats = [] self.extra_files = [] - self.failed_folders = [] - self.books = [] - self.conflicting_custom_cols = {} - self.failed_restores = [] - self.mismatched_dirs = [] - self.successes = 0 - self.tb = None def dbpath(self, id): return self.db.path(id, index_is_id=True) @@ -71,34 +68,6 @@ class CheckLibrary(object): return self.failed_folders or self.mismatched_dirs or \ self.conflicting_custom_cols or self.failed_restores - @property - def report(self): - ans = '' - failures = list(self.failed_folders) + [(x['dirpath'], tb) for x, tb in - self.failed_restores] - if failures: - ans += 'Failed to restore the books in the following folders:\n' - for dirpath, tb in failures: - ans += '\t' + dirpath + ' with error:\n' - ans += '\n'.join('\t\t'+x for x in tb.splitlines()) - ans += '\n\n' - - if self.conflicting_custom_cols: - ans += '\n\n' - ans += 'The following custom columns were not fully restored:\n' - for x in self.conflicting_custom_cols: - ans += '\t#'+x+'\n' - - if self.mismatched_dirs: - ans += '\n\n' - ans += 'The following folders were ignored:\n' - for x in self.mismatched_dirs: - ans += '\t'+x+'\n' - - - return ans - - def scan_library(self): lib = self.src_library_path for auth_dir in os.listdir(lib): @@ -123,10 +92,16 @@ class CheckLibrary(object): id = m.group(1) # Third check: the id must be in the DB and the paths must match - if int(id) not in self.all_ids or \ - db_path not in self.all_dbpaths: - self.extra_titles.append((title_dir, db_path, [])) - continue + if self.is_case_sensitive: + if int(id) not in self.all_ids or \ + db_path not in self.all_dbpaths: + self.extra_titles.append((title_dir, db_path, [])) + continue + else: + if int(id) not in self.all_ids or \ + db_path.lower() not in self.all_lc_dbpaths: + self.extra_titles.append((title_dir, db_path, [])) + continue # Record the book to check its formats self.book_dirs.append((db_path, title_dir, id)) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 05c24f1ce8..d504e670e0 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -875,19 +875,23 @@ def command_saved_searches(args, dbpath): return 0 def check_library_option_parser(): - from calibre.library.custom_columns import CustomColumns + from calibre.library.check_library import CHECKS parser = get_parser(_('''\ %prog check_library [options] -Perform some checks on the filesystem representing a library. -''').format(', '.join(CustomColumns.CUSTOM_DATA_TYPES))) +Perform some checks on the filesystem representing a library. Reports are {0} +''').format(', '.join([c[0] for c in CHECKS]))) parser.add_option('-c', '--csv', default=False, action='store_true', help=_('Output in CSV')) + + parser.add_option('-r', '--report', default=None, dest='report', + help=_("Comma-separated list of reports.\n" + "Default: all")) return parser def command_check_library(args, dbpath): - from calibre.library.check_library import CheckLibrary + from calibre.library.check_library import CheckLibrary, CHECKS parser = check_library_option_parser() opts, args = parser.parse_args(args) if len(args) != 0: @@ -900,6 +904,21 @@ def command_check_library(args, dbpath): if isbytestring(dbpath): dbpath = dbpath.decode(preferred_encoding) + if opts.report is None: + checks = CHECKS + else: + checks = [] + for r in opts.report.split(','): + found = False + for c in CHECKS: + if c[0] == r: + checks.append(c) + found = True + break + if not found: + print _('Unknown report check'), r + return 1 + def print_one(checker, check): attr = check[0] list = getattr(checker, attr, None) @@ -916,7 +935,7 @@ def command_check_library(args, dbpath): db = LibraryDatabase2(dbpath) checker = CheckLibrary(dbpath, db) checker.scan_library() - for check in checker.checks: + for check in checks: print_one(checker, check)