diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index b5e3013f61..c633244e1b 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -989,8 +989,8 @@ class DB: id_val = self.tables[field].id_map[item_id] return self.notes.unretire(self.conn, field, item_id, id_val) - def add_notes_resource(self, path_or_stream, name) -> int: - return self.notes.add_resource(self.conn, path_or_stream, name) + def add_notes_resource(self, path_or_stream, name, mtime=None) -> int: + return self.notes.add_resource(self.conn, path_or_stream, name, mtime=mtime) def get_notes_resource(self, resource_hash) -> Optional[dict]: return self.notes.get_resource_data(self.conn, resource_hash) diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index ef6ca9284c..314dbebea2 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -20,7 +20,7 @@ from functools import partial, wraps from io import DEFAULT_BUFFER_SIZE, BytesIO from queue import Queue from threading import Lock -from time import monotonic, sleep, time +from time import mktime, monotonic, sleep, time from typing import NamedTuple, Optional, Tuple from calibre import as_unicode, detect_ncpus, isbytestring @@ -724,9 +724,9 @@ class Cache: return self.backend.set_notes_for(field, item_id, doc, searchable_text, resource_hashes, remove_unused_resources) @write_api - def add_notes_resource(self, path_or_stream_or_data, name: str) -> int: + def add_notes_resource(self, path_or_stream_or_data, name: str, mtime: float = None) -> int: ' Add the specified resource so it can be referenced by notes and return its content hash ' - return self.backend.add_notes_resource(path_or_stream_or_data, name) + return self.backend.add_notes_resource(path_or_stream_or_data, name, mtime) @read_api def get_notes_resource(self, resource_hash) -> Optional[dict]: @@ -3460,7 +3460,10 @@ def import_library(library_key, importer, library_path, progress=None, abort=Non with closing(importer.start_file(metadata['notes.db'], 'notes.db for ' + library_path)) as stream: stream.check_hash = False with zipfile.ZipFile(stream) as zf: - zf.extractall(notes_dir) + for zi in zf.infolist(): + tpath = zf._extract_member(zi, notes_dir, None) + date_time = mktime(zi.date_time + (0, 0, -1)) + os.utime(tpath, (date_time, date_time)) if abort is not None and abort.is_set(): return cache = Cache(DB(library_path, load_user_formatter_functions=False)) diff --git a/src/calibre/db/notes/connect.py b/src/calibre/db/notes/connect.py index 15c75ebc8a..e4a4735528 100644 --- a/src/calibre/db/notes/connect.py +++ b/src/calibre/db/notes/connect.py @@ -306,7 +306,7 @@ class Notes: for path in items[:extra]: remove_with_retry(path, is_dir=True) - def add_resource(self, conn, path_or_stream_or_data, name, update_name=True): + def add_resource(self, conn, path_or_stream_or_data, name, update_name=True, mtime=None): if isinstance(path_or_stream_or_data, bytes): data = path_or_stream_or_data elif isinstance(path_or_stream_or_data, str): @@ -332,6 +332,9 @@ class Notes: f = open(path, 'wb') with f: f.write(data) + if mtime is not None: + os.utime(f.name, (mtime, mtime)) + name = sanitize_file_name(name) base_name, ext = os.path.splitext(name) c = 0 diff --git a/src/calibre/db/tests/filesystem.py b/src/calibre/db/tests/filesystem.py index 4784236ce5..476404168b 100644 --- a/src/calibre/db/tests/filesystem.py +++ b/src/calibre/db/tests/filesystem.py @@ -264,8 +264,8 @@ class FilesystemTest(BaseTest): bookdir = os.path.dirname(ic.format_abspath(1, '__COVER_INTERNAL__')) self.assertEqual('exf', open(os.path.join(bookdir, 'exf')).read()) self.assertEqual('recurse', open(os.path.join(bookdir, 'sub', 'recurse')).read()) - r1 = cache.add_notes_resource(b'res1', 'res.jpg') - r2 = cache.add_notes_resource(b'res2', 'res.jpg') + r1 = cache.add_notes_resource(b'res1', 'res.jpg', mtime=time.time()-113) + r2 = cache.add_notes_resource(b'res2', 'res.jpg', mtime=time.time()-1115) cache.set_notes_for('authors', 2, 'some notes', resource_hashes=(r1, r2)) cache.add_format(1, 'TXT', BytesIO(b'testing exim')) cache.fts_indexing_sleep_time = 0.001 @@ -285,7 +285,10 @@ class FilesystemTest(BaseTest): ic = import_library('l', importer, idir) self.assertEqual(ic.fts_search('exim')[0]['id'], 1) self.assertEqual(cache.notes_for('authors', 2), ic.notes_for('authors', 2)) - self.assertEqual(cache.get_notes_resource(r1), ic.get_notes_resource(r1)) + a, b = cache.get_notes_resource(r1), ic.get_notes_resource(r1) + at, bt, = a.pop('mtime'), b.pop('mtime') + self.assertEqual(a, b) + self.assertLess(abs(at-bt), 2) def test_find_books_in_directory(self): from calibre.db.adding import find_books_in_directory, compile_rule diff --git a/src/calibre/db/tests/notes.py b/src/calibre/db/tests/notes.py index 75c8ebd759..b220ec49ae 100644 --- a/src/calibre/db/tests/notes.py +++ b/src/calibre/db/tests/notes.py @@ -151,6 +151,10 @@ def test_cache_api(self: 'NotesTest'): self.assertGreater(note_id, 0) self.assertIn('

test simple exim