From dac0ff659076650c1fbb5702b4ed99f01ccaeaa7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 27 May 2014 07:34:02 +0530 Subject: [PATCH] Check Book: When reporting unmanifested file warnings, allow auto fixing by adding the file to the manifest if it is referenced elsewhere or removing the file if it is not. Fixes #1323362 [Automatic fix does not work for "file is not listed in the book manifest."](https://bugs.launchpad.net/calibre/+bug/1323362) --- src/calibre/ebooks/oeb/polish/check/links.py | 15 ++++++++-- src/calibre/ebooks/oeb/polish/container.py | 30 ++++++++++++-------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/calibre/ebooks/oeb/polish/check/links.py b/src/calibre/ebooks/oeb/polish/check/links.py index abb80e856c..cddbecbabd 100644 --- a/src/calibre/ebooks/oeb/polish/check/links.py +++ b/src/calibre/ebooks/oeb/polish/check/links.py @@ -95,10 +95,21 @@ class Unmanifested(BadLink): ' it is good practice to list all files in the manifest. Either list this' ' file in the manifest or remove it from the book if it is an unnecessary file.') - def __init__(self, name): + def __init__(self, name, unreferenced=None): BadLink.__init__(self, _( 'The file %s is not listed in the manifest') % name, name) + self.file_action = None + if unreferenced is not None: + self.INDIVIDUAL_FIX = _( + 'Remove %s from the book') % name if unreferenced else _( + 'Add %s to the manifest') % name + self.file_action = 'remove' if unreferenced else 'add' + def __call__(self, container): + if self.file_action == 'remove': + container.remove_item(self.name) + else: + container.add_name_to_manifest(self.name) class Bookmarks(BadLink): @@ -251,7 +262,7 @@ def check_links(container): manifest_names = set(container.manifest_id_map.itervalues()) for name in container.mime_map: if name not in manifest_names and not container.ok_to_be_unmanifested(name): - a(Unmanifested(name)) + a(Unmanifested(name, unreferenced=name in unreferenced)) if name == 'META-INF/calibre_bookmarks.txt': a(Bookmarks(name)) diff --git a/src/calibre/ebooks/oeb/polish/container.py b/src/calibre/ebooks/oeb/polish/container.py index 61a645badf..3fc21d1bb7 100644 --- a/src/calibre/ebooks/oeb/polish/container.py +++ b/src/calibre/ebooks/oeb/polish/container.py @@ -171,6 +171,22 @@ class Container(object): # {{{ ans = 'application/xhtml+xml' return ans + def add_name_to_manifest(self, name): + all_ids = {x.get('id') for x in self.opf_xpath('//*[@id]')} + c = 0 + item_id = 'id' + while item_id in all_ids: + c += 1 + item_id = 'id' + '%d'%c + manifest = self.opf_xpath('//opf:manifest')[0] + href = self.name_to_href(name, self.opf_name) + item = manifest.makeelement(OPF('item'), + id=item_id, href=href) + item.set('media-type', self.mime_map[name]) + self.insert_into_xml(manifest, item) + self.dirty(self.opf_name) + return item_id + def add_file(self, name, data, media_type=None, spine_index=None): ''' Add a file to this container. Entries for the file are automatically created in the OPF manifest and spine @@ -194,19 +210,9 @@ class Container(object): # {{{ self.mime_map[name] = mt if self.ok_to_be_unmanifested(name): return - all_ids = {x.get('id') for x in self.opf_xpath('//*[@id]')} - c = 0 - item_id = 'id' - while item_id in all_ids: - c += 1 - item_id = 'id' + '%d'%c - manifest = self.opf_xpath('//opf:manifest')[0] - item = manifest.makeelement(OPF('item'), - id=item_id, href=href) - item.set('media-type', mt) - self.insert_into_xml(manifest, item) - self.dirty(self.opf_name) + item_id = self.add_name_to_manifest(name) if mt in OEB_DOCS: + manifest = self.opf_xpath('//opf:manifest')[0] spine = self.opf_xpath('//opf:spine')[0] si = manifest.makeelement(OPF('itemref'), idref=item_id) self.insert_into_xml(spine, si, index=spine_index)