diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index e7af550f0b..75fc8cb771 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -1456,6 +1456,15 @@ class DB: self.user_version = 1 # }}} + def clone_for_readonly_access(self, dest_dir: str) -> str: + dbpath = os.path.abspath(self.conn.db_filename('main')) + clone_db_path = os.path.join(dest_dir, os.path.basename(dbpath)) + shutil.copy2(dbpath, clone_db_path) + notes_dir = os.path.join(os.path.dirname(dbpath), NOTES_DIR_NAME) + if os.path.exists(notes_dir): + shutil.copytree(notes_dir, os.path.join(dest_dir, NOTES_DIR_NAME)) + return clone_db_path + def normpath(self, path): path = os.path.abspath(os.path.realpath(path)) if not self.is_case_sensitive: diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index 8bd77968b3..6a76c5e852 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -3513,6 +3513,10 @@ class Cache: dest_value.extend(src_value) self._set_field(field, {dest_id: dest_value}) + @read_api + def clone_for_readonly_access(self, dest_dir: str) -> str: + return self.backend.clone_for_readonly_access(dest_dir) + def import_library(library_key, importer, library_path, progress=None, abort=None): from calibre.db.backend import DB diff --git a/src/calibre/gui2/convert/gui_conversion.py b/src/calibre/gui2/convert/gui_conversion.py index 9791bd5873..ce21d3f4ee 100644 --- a/src/calibre/gui2/convert/gui_conversion.py +++ b/src/calibre/gui2/convert/gui_conversion.py @@ -41,7 +41,7 @@ def gui_convert_override(input, output, recommendations, notification=DummyRepor def gui_catalog(library_path, temp_db_path, fmt, title, dbspec, ids, out_file_name, sync, fmt_options, connected_device, - notification=DummyReporter(), log=None): + notification=DummyReporter(), log=None): if log is None: log = Log() from calibre.utils.config import prefs @@ -50,31 +50,36 @@ def gui_catalog(library_path, temp_db_path, fmt, title, dbspec, ids, out_file_na # Open the temp database created while still in the GUI thread from calibre.db.legacy import LibraryDatabase db = LibraryDatabase(library_path, temp_db_path=temp_db_path) - db.catalog_plugin_on_device_temp_mapping = dbspec + try: + db.catalog_plugin_on_device_temp_mapping = dbspec - # Create a minimal OptionParser that we can append to - parser = OptionParser() - args = [] - parser.add_option('--verbose', action='store_true', dest='verbose', default=True) - opts, args = parser.parse_args() + # Create a minimal OptionParser that we can append to + parser = OptionParser() + args = [] + parser.add_option('--verbose', action='store_true', dest='verbose', default=True) + opts, args = parser.parse_args() - # Populate opts - # opts.gui_search_text = something - opts.catalog_title = title - opts.connected_device = connected_device - opts.ids = ids - opts.search_text = None - opts.sort_by = None - opts.sync = sync + # Populate opts + # opts.gui_search_text = something + opts.catalog_title = title + opts.connected_device = connected_device + opts.ids = ids + opts.search_text = None + opts.sort_by = None + opts.sync = sync - # Extract the option dictionary to comma-separated lists - for option in fmt_options: - if isinstance(fmt_options[option],list): - setattr(opts, option, ','.join(fmt_options[option])) - else: - setattr(opts, option, fmt_options[option]) + # Extract the option dictionary to comma-separated lists + for option in fmt_options: + if isinstance(fmt_options[option],list): + setattr(opts, option, ','.join(fmt_options[option])) + else: + setattr(opts, option, fmt_options[option]) - # Fetch and run the plugin for fmt - # Returns 0 if successful, 1 if no catalog built - plugin = plugin_for_catalog_format(fmt) - return plugin.run(out_file_name, opts, db, notification=notification) + # Fetch and run the plugin for fmt + # Returns 0 if successful, 1 if no catalog built + plugin = plugin_for_catalog_format(fmt) + return plugin.run(out_file_name, opts, db, notification=notification) + finally: + import shutil + db.close() + shutil.rmtree(os.path.dirname(temp_db_path)) diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 6f699e8076..ca6b2f31f9 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -10,7 +10,6 @@ Logic for setting up conversion jobs ''' import os -import shutil from qt.core import QDialog, QProgressDialog, QTimer @@ -376,18 +375,12 @@ def generate_catalog(parent, dbspec, ids, device_manager, db): # {{{ # process. The backend looks for the notes directory (.calnotes) in the # directory containing the metadata.db file. Copy the one from the current # library. - from calibre.gui2.ui import get_gui - library_path = get_gui().current_db.library_path - temp_db_directory = PersistentTemporaryDirectory('_callib') - temp_db_path = os.path.join(temp_db_directory, 'metadata.db') - shutil.copy(os.path.join(library_path, 'metadata.db'), temp_db_directory) - notes_dir = os.path.join(library_path, '.calnotes') - if os.path.exists(notes_dir): - shutil.copytree(notes_dir, os.path.join(temp_db_directory, '.calnotes')) + temp_db_directory = PersistentTemporaryDirectory('callib') + temp_db_path = db.new_api.clone_for_readonly_access(temp_db_directory) # These args are passed inline to gui2.convert.gui_conversion:gui_catalog args = [ - library_path, + db.library_path, temp_db_path, d.catalog_format, d.catalog_title,