calibredb add_format: Add support for adding extra data files

This commit is contained in:
Kovid Goyal 2023-04-19 17:39:47 +05:30
parent b45ca52f0f
commit 2f6cd98741
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 29 additions and 6 deletions

View File

@ -1936,8 +1936,10 @@ class DB:
with src: with src:
yield relpath, src, mtime yield relpath, src, mtime
def add_extra_file(self, relpath, stream, book_path): def add_extra_file(self, relpath, stream, book_path, replace=True):
dest = os.path.abspath(os.path.join(self.library_path, book_path, relpath)) dest = os.path.abspath(os.path.join(self.library_path, book_path, relpath))
if not replace and os.path.exists(dest):
return False
if isinstance(stream, str): if isinstance(stream, str):
try: try:
shutil.copy2(stream, dest) shutil.copy2(stream, dest)
@ -1952,6 +1954,7 @@ class DB:
d = open(dest, 'wb') d = open(dest, 'wb')
with d: with d:
shutil.copyfileobj(stream, d) shutil.copyfileobj(stream, d)
return True
def write_backup(self, path, raw): def write_backup(self, path, raw):
path = os.path.abspath(os.path.join(self.library_path, path, METADATA_FILE_NAME)) path = os.path.abspath(os.path.join(self.library_path, path, METADATA_FILE_NAME))

View File

@ -3050,11 +3050,13 @@ class Cache:
self.backend.reindex_annotations() self.backend.reindex_annotations()
@write_api @write_api
def add_extra_files(self, book_id, map_of_relpath_to_stream_or_path): def add_extra_files(self, book_id, map_of_relpath_to_stream_or_path, replace=True):
' Add extra data files ' ' Add extra data files '
path = self._field_for('path', book_id).replace('/', os.sep) path = self._field_for('path', book_id).replace('/', os.sep)
added = {}
for relpath, stream_or_path in map_of_relpath_to_stream_or_path.items(): for relpath, stream_or_path in map_of_relpath_to_stream_or_path.items():
self.backend.add_extra_file(relpath, stream_or_path, path) added[relpath] = self.backend.add_extra_file(relpath, stream_or_path, path, replace)
return added
@read_api @read_api
def list_extra_files_matching(self, book_id, pattern=''): def list_extra_files_matching(self, book_id, pattern=''):

View File

@ -15,8 +15,14 @@ def implementation(db, notify_changes, book_id, data, fmt, replace):
is_remote = notify_changes is not None is_remote = notify_changes is not None
if is_remote: if is_remote:
data = BytesIO(data[1]) data = BytesIO(data[1])
added = db.add_format(book_id, fmt, data, replace=replace) relpath = ''
if is_remote and added: if fmt.startswith('.EXTRA_DATA_FILE:'):
relpath = fmt[len('.EXTRA_DATA_FILE:'):]
if relpath:
added = db.add_extra_files(book_id, {relpath: data}, replace=replace)[relpath]
else:
added = db.add_format(book_id, fmt, data, replace=replace)
if is_remote and added and not relpath:
notify_changes(formats_added({book_id: (fmt,)})) notify_changes(formats_added({book_id: (fmt,)}))
return added return added
@ -40,6 +46,13 @@ it is replaced, unless the do not replace option is specified.\
action='store_false', action='store_false',
help=_('Do not replace the format if it already exists') help=_('Do not replace the format if it already exists')
) )
parser.add_option(
'--as-extra-data-file',
default=False,
action='store_true',
help=_('Add the file as an extra data file to the book, not an ebook format')
)
return parser return parser
@ -48,9 +61,14 @@ def main(opts, args, dbctx):
raise SystemExit(_('You must specify an id and an e-book file')) raise SystemExit(_('You must specify an id and an e-book file'))
id, path, fmt = int(args[0]), args[1], os.path.splitext(args[1])[-1] id, path, fmt = int(args[0]), args[1], os.path.splitext(args[1])[-1]
if opts.as_extra_data_file:
fmt = '.EXTRA_DATA_FILE:' + 'data/' + os.path.basename(args[1])
else:
fmt = fmt[1:].upper()
if not fmt: if not fmt:
raise SystemExit(_('e-book file must have an extension')) raise SystemExit(_('e-book file must have an extension'))
fmt = fmt[1:].upper()
if not dbctx.run('add_format', id, dbctx.path(path), fmt, opts.replace): if not dbctx.run('add_format', id, dbctx.path(path), fmt, opts.replace):
if opts.as_extra_data_file:
raise SystemExit(f'An extra data file with the filename {os.path.basename(args[1])} already exists')
raise SystemExit(_('A %(fmt)s file already exists for book: %(id)d, not replacing')%dict(fmt=fmt, id=id)) raise SystemExit(_('A %(fmt)s file already exists for book: %(id)d, not replacing')%dict(fmt=fmt, id=id))
return 0 return 0