mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-08-11 09:13:57 -04:00
Merge from trunk
This commit is contained in:
commit
076fbd204a
1260
setup/iso_639/de.po
1260
setup/iso_639/de.po
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ from calibre.ptempfile import (PersistentTemporaryFile,
|
|||||||
base_dir, SpooledTemporaryFile)
|
base_dir, SpooledTemporaryFile)
|
||||||
from calibre.customize.ui import run_plugins_on_import
|
from calibre.customize.ui import run_plugins_on_import
|
||||||
from calibre import isbytestring
|
from calibre import isbytestring
|
||||||
from calibre.utils.filenames import ascii_filename
|
from calibre.utils.filenames import ascii_filename, samefile
|
||||||
from calibre.utils.date import (utcnow, now as nowf, utcfromtimestamp,
|
from calibre.utils.date import (utcnow, now as nowf, utcfromtimestamp,
|
||||||
parse_only_date)
|
parse_only_date)
|
||||||
from calibre.utils.config import prefs, tweaks, from_json, to_json
|
from calibre.utils.config import prefs, tweaks, from_json, to_json
|
||||||
@ -618,7 +618,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
def normpath(self, path):
|
def normpath(self, path):
|
||||||
path = os.path.abspath(os.path.realpath(path))
|
path = os.path.abspath(os.path.realpath(path))
|
||||||
if not self.is_case_sensitive:
|
if not self.is_case_sensitive:
|
||||||
path = path.lower()
|
path = os.path.normcase(path).lower()
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def set_path(self, index, index_is_id=False):
|
def set_path(self, index, index_is_id=False):
|
||||||
@ -654,21 +654,20 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
with lopen(os.path.join(tpath, 'cover.jpg'), 'wb') as f:
|
with lopen(os.path.join(tpath, 'cover.jpg'), 'wb') as f:
|
||||||
f.write(cdata)
|
f.write(cdata)
|
||||||
for format in formats:
|
for format in formats:
|
||||||
with SpooledTemporaryFile(SPOOL_SIZE) as stream:
|
copy_function = functools.partial(self.copy_format_to, id,
|
||||||
|
format, index_is_id=True)
|
||||||
try:
|
try:
|
||||||
self.copy_format_to(id, format, stream, index_is_id=True)
|
self.add_format(id, format, None, index_is_id=True,
|
||||||
stream.seek(0)
|
path=tpath, notify=False, copy_function=copy_function)
|
||||||
except NoSuchFormat:
|
except NoSuchFormat:
|
||||||
continue
|
continue
|
||||||
self.add_format(id, format, stream, index_is_id=True,
|
|
||||||
path=tpath, notify=False)
|
|
||||||
self.conn.execute('UPDATE books SET path=? WHERE id=?', (path, id))
|
self.conn.execute('UPDATE books SET path=? WHERE id=?', (path, id))
|
||||||
self.dirtied([id], commit=False)
|
self.dirtied([id], commit=False)
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
self.data.set(id, self.FIELD_MAP['path'], path, row_is_id=True)
|
self.data.set(id, self.FIELD_MAP['path'], path, row_is_id=True)
|
||||||
# Delete not needed directories
|
# Delete not needed directories
|
||||||
if current_path and os.path.exists(spath):
|
if current_path and os.path.exists(spath):
|
||||||
if self.normpath(spath) != self.normpath(tpath):
|
if not samefile(spath, tpath):
|
||||||
self.rmtree(spath, permanent=True)
|
self.rmtree(spath, permanent=True)
|
||||||
parent = os.path.dirname(spath)
|
parent = os.path.dirname(spath)
|
||||||
if len(os.listdir(parent)) == 0:
|
if len(os.listdir(parent)) == 0:
|
||||||
@ -1343,15 +1342,22 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
'''
|
'''
|
||||||
Copy the format ``fmt`` to the file like object ``dest``. If the
|
Copy the format ``fmt`` to the file like object ``dest``. If the
|
||||||
specified format does not exist, raises :class:`NoSuchFormat` error.
|
specified format does not exist, raises :class:`NoSuchFormat` error.
|
||||||
|
dest can also be a path, in which case the format is copied to it, iff
|
||||||
|
the path is different from the current path (taking case sensitivity
|
||||||
|
into account).
|
||||||
'''
|
'''
|
||||||
path = self.format_abspath(index, fmt, index_is_id=index_is_id)
|
path = self.format_abspath(index, fmt, index_is_id=index_is_id)
|
||||||
if path is None:
|
if path is None:
|
||||||
id_ = index if index_is_id else self.id(index)
|
id_ = index if index_is_id else self.id(index)
|
||||||
raise NoSuchFormat('Record %d has no %s file'%(id_, fmt))
|
raise NoSuchFormat('Record %d has no %s file'%(id_, fmt))
|
||||||
|
if hasattr(dest, 'write'):
|
||||||
with lopen(path, 'rb') as f:
|
with lopen(path, 'rb') as f:
|
||||||
shutil.copyfileobj(f, dest)
|
shutil.copyfileobj(f, dest)
|
||||||
if hasattr(dest, 'flush'):
|
if hasattr(dest, 'flush'):
|
||||||
dest.flush()
|
dest.flush()
|
||||||
|
elif dest and not samefile(dest, path):
|
||||||
|
with lopen(path, 'rb') as f, lopen(dest, 'wb') as d:
|
||||||
|
shutil.copyfileobj(f, d)
|
||||||
|
|
||||||
def format(self, index, format, index_is_id=False, as_file=False,
|
def format(self, index, format, index_is_id=False, as_file=False,
|
||||||
mode='r+b', as_path=False, preserve_filename=False):
|
mode='r+b', as_path=False, preserve_filename=False):
|
||||||
@ -1411,7 +1417,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
index_is_id=index_is_id, path=path, notify=notify)
|
index_is_id=index_is_id, path=path, notify=notify)
|
||||||
|
|
||||||
def add_format(self, index, format, stream, index_is_id=False, path=None,
|
def add_format(self, index, format, stream, index_is_id=False, path=None,
|
||||||
notify=True, replace=True):
|
notify=True, replace=True, copy_function=None):
|
||||||
id = index if index_is_id else self.id(index)
|
id = index if index_is_id else self.id(index)
|
||||||
if not format: format = ''
|
if not format: format = ''
|
||||||
self.format_metadata_cache[id].pop(format.upper(), None)
|
self.format_metadata_cache[id].pop(format.upper(), None)
|
||||||
@ -1426,12 +1432,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
pdir = os.path.dirname(dest)
|
pdir = os.path.dirname(dest)
|
||||||
if not os.path.exists(pdir):
|
if not os.path.exists(pdir):
|
||||||
os.makedirs(pdir)
|
os.makedirs(pdir)
|
||||||
if not getattr(stream, 'name', False) or \
|
if copy_function is not None:
|
||||||
os.path.abspath(dest) != os.path.abspath(stream.name):
|
copy_function(dest)
|
||||||
|
size = os.path.getsize(dest)
|
||||||
|
else:
|
||||||
|
if (not getattr(stream, 'name', False) or not samefile(dest,
|
||||||
|
stream.name)):
|
||||||
with lopen(dest, 'wb') as f:
|
with lopen(dest, 'wb') as f:
|
||||||
shutil.copyfileobj(stream, f)
|
shutil.copyfileobj(stream, f)
|
||||||
stream.seek(0, 2)
|
size = f.tell()
|
||||||
size=stream.tell()
|
|
||||||
self.conn.execute('INSERT OR REPLACE INTO data (book,format,uncompressed_size,name) VALUES (?,?,?,?)',
|
self.conn.execute('INSERT OR REPLACE INTO data (book,format,uncompressed_size,name) VALUES (?,?,?,?)',
|
||||||
(id, format.upper(), size, name))
|
(id, format.upper(), size, name))
|
||||||
self.update_last_modified([id], commit=False)
|
self.update_last_modified([id], commit=False)
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
20882
src/calibre/translations/ka.po
Normal file
20882
src/calibre/translations/ka.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
20880
src/calibre/translations/sr@latin.po
Normal file
20880
src/calibre/translations/sr@latin.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -199,3 +199,45 @@ def case_preserving_open_file(path, mode='wb', mkdir_mode=0777):
|
|||||||
fpath = os.path.join(cpath, fname)
|
fpath = os.path.join(cpath, fname)
|
||||||
return ans, fpath
|
return ans, fpath
|
||||||
|
|
||||||
|
def samefile_windows(src, dst):
|
||||||
|
import win32file
|
||||||
|
from pywintypes import error
|
||||||
|
|
||||||
|
def get_fileid(x):
|
||||||
|
if isbytestring(x): x = x.decode(filesystem_encoding)
|
||||||
|
try:
|
||||||
|
h = win32file.CreateFile(x, 0, 0, None, win32file.OPEN_EXISTING,
|
||||||
|
win32file.FILE_FLAG_BACKUP_SEMANTICS, 0)
|
||||||
|
data = win32file.GetFileInformationByHandle(h)
|
||||||
|
except (error, EnvironmentError):
|
||||||
|
return None
|
||||||
|
return (data[4], data[8], data[9])
|
||||||
|
|
||||||
|
a, b = get_fileid(src), get_fileid(dst)
|
||||||
|
if a is None and b is None:
|
||||||
|
return False
|
||||||
|
return a == b
|
||||||
|
|
||||||
|
def samefile(src, dst):
|
||||||
|
'''
|
||||||
|
Check if two paths point to the same actual file on the filesystem. Handles
|
||||||
|
symlinks, case insensitivity, mapped drives, etc.
|
||||||
|
|
||||||
|
Returns True iff both paths exist and point to the same file on disk.
|
||||||
|
'''
|
||||||
|
if iswindows:
|
||||||
|
return samefile_windows(src, dst)
|
||||||
|
|
||||||
|
if hasattr(os.path, 'samefile'):
|
||||||
|
# Unix
|
||||||
|
try:
|
||||||
|
return os.path.samefile(src, dst)
|
||||||
|
except EnvironmentError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# All other platforms: check for same pathname.
|
||||||
|
samestring = (os.path.normcase(os.path.abspath(src)) ==
|
||||||
|
os.path.normcase(os.path.abspath(dst)))
|
||||||
|
return samestring
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user