From 58c0127a17bcd8150b60e1c265e6ecc76b62a2e5 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 15 Jan 2013 09:47:50 +0100 Subject: [PATCH] Add an option to the smart device driver (default: True) that tells the driver that when sending a book, overwrite a book on the device if it has the same UUID, ignoring the result of evaluating the template. This prevents accumulating multiple copies of books when metadata changes. --- .../devices/smart_device_app/driver.py | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index e22a0142be..37292973c0 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -300,19 +300,21 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): 'particular IP address. The driver will listen only on the ' 'entered address, and this address will be the one advertized ' 'over mDNS (bonjour).') + '

', + _('Overwrite books with same UUID') + ':::

' + + _('Use this option to overwrite a book on the device if that book ' + 'has the same UUID as the book being sent. The file name of the ' + 'book will not change even if the save template produces a ' + 'different result. Using this option in most cases prevents ' + 'having multiple copies of a book on the device.') + '

', ] EXTRA_CUSTOMIZATION_DEFAULT = [ - False, - '', - '', - '', + False, '', + '', '', False, '9090', - False, - '', - '', - '', - True, - '' + False, '', + '', '', + True, '', + True ] OPT_AUTOSTART = 0 OPT_PASSWORD = 2 @@ -322,6 +324,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): OPT_COLLECTIONS = 8 OPT_AUTODISCONNECT = 10 OPT_FORCE_IP_ADDRESS = 11 + OPT_OVERWRITE_BOOKS_UUID = 12 def __init__(self, path): @@ -386,8 +389,14 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): ext = os.path.splitext(fname)[1] try: + # If we have already seen this book's UUID, use the existing path + if self.settings().extra_customization[self.OPT_OVERWRITE_BOOKS_UUID]: + existing_book = self._uuid_already_on_device(mdata.uuid) + if existing_book and existing_book.lpath: + return existing_book.lpath + # If the device asked for it, try to use the UUID as the file name. - # Fall back to the template if the UUID doesn't exist. + # Fall back to the ch if the UUID doesn't exist. if self.client_wants_uuid_file_names and mdata.uuid: return (mdata.uuid + ext) except: @@ -679,12 +688,20 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): return not v_thumb or v_thumb[1] == b_thumb[1] return False + def _uuid_already_on_device(self, uuid): + return self.known_uuids.get(uuid, None) + def _set_known_metadata(self, book, remove=False): lpath = book.lpath + uuid = book.get('uuid', None) if remove: self.known_metadata.pop(lpath, None) + if uuid: + self.known_uuids.pop(uuid, None) else: - self.known_metadata[lpath] = book.deepcopy() + new_book = self.known_metadata[lpath] = book.deepcopy() + if uuid: + self.known_uuids[uuid] = new_book def _close_device_socket(self): if self.device_socket is not None: @@ -1097,6 +1114,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): for i, infile in enumerate(files): mdata, fname = metadata.next(), names.next() lpath = self._create_upload_path(mdata, fname, create_dirs=False) + self._debug('lpath', lpath) if not hasattr(infile, 'read'): infile = USBMS.normalize_path(infile) book = SDBook(self.PREFIX, lpath, other=mdata) @@ -1258,6 +1276,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): self.device_socket = None self.json_codec = JsonCodec() self.known_metadata = {} + self.known_uuids = {} self.debug_time = time.time() self.debug_start_time = time.time() self.max_book_packet_len = 0