mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Windows: Check if any of the files of a book are in use before changing the title/author, this (usually) prevents the creation of duplicate files if one of the files is open in another program
This commit is contained in:
parent
d24835bff8
commit
1db24f5192
@ -270,7 +270,7 @@ class AuthorsEdit(EditWithComplete):
|
|||||||
import traceback
|
import traceback
|
||||||
fname = err.filename if err.filename else 'file'
|
fname = err.filename if err.filename else 'file'
|
||||||
error_dialog(self, _('Permission denied'),
|
error_dialog(self, _('Permission denied'),
|
||||||
_('Could not open %s. Is it being used by another'
|
_('Could not open "%s". Is it being used by another'
|
||||||
' program?')%fname, det_msg=traceback.format_exc(),
|
' program?')%fname, det_msg=traceback.format_exc(),
|
||||||
show=True)
|
show=True)
|
||||||
return False
|
return False
|
||||||
|
@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
The database used to store ebook metadata
|
The database used to store ebook metadata
|
||||||
'''
|
'''
|
||||||
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \
|
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \
|
||||||
json, uuid, hashlib, copy
|
json, uuid, hashlib, copy, errno
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import threading, random
|
import threading, random
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
@ -30,7 +30,8 @@ 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, samefile
|
from calibre.utils.filenames import (ascii_filename, samefile,
|
||||||
|
windows_is_folder_in_use)
|
||||||
from calibre.utils.date import (utcnow, now as nowf, utcfromtimestamp,
|
from calibre.utils.date import (utcnow, now as nowf, utcfromtimestamp,
|
||||||
parse_only_date, UNDEFINED_DATE)
|
parse_only_date, UNDEFINED_DATE)
|
||||||
from calibre.utils.config import prefs, tweaks, from_json, to_json
|
from calibre.utils.config import prefs, tweaks, from_json, to_json
|
||||||
@ -649,6 +650,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
spath = os.path.join(self.library_path, *current_path.split('/'))
|
spath = os.path.join(self.library_path, *current_path.split('/'))
|
||||||
|
|
||||||
if current_path and os.path.exists(spath): # Migrate existing files
|
if current_path and os.path.exists(spath): # Migrate existing files
|
||||||
|
if iswindows:
|
||||||
|
uf = windows_is_folder_in_use(spath)
|
||||||
|
if uf is not None:
|
||||||
|
err = IOError(errno.EACCES,
|
||||||
|
_('File is open in another process'))
|
||||||
|
err.filename = uf
|
||||||
|
raise err
|
||||||
cdata = self.cover(id, index_is_id=True)
|
cdata = self.cover(id, index_is_id=True)
|
||||||
if cdata is not None:
|
if cdata is not None:
|
||||||
with lopen(os.path.join(tpath, 'cover.jpg'), 'wb') as f:
|
with lopen(os.path.join(tpath, 'cover.jpg'), 'wb') as f:
|
||||||
|
@ -249,4 +249,32 @@ def samefile(src, dst):
|
|||||||
os.path.normcase(os.path.abspath(dst)))
|
os.path.normcase(os.path.abspath(dst)))
|
||||||
return samestring
|
return samestring
|
||||||
|
|
||||||
|
def windows_is_file_opened(path):
|
||||||
|
import win32file, winerror
|
||||||
|
from pywintypes import error
|
||||||
|
if isbytestring(path): path = path.decode(filesystem_encoding)
|
||||||
|
try:
|
||||||
|
h = win32file.CreateFile(path, win32file.GENERIC_READ, 0, None,
|
||||||
|
win32file.OPEN_EXISTING, 0, 0)
|
||||||
|
except error as e:
|
||||||
|
if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
win32file.CloseHandle(h)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def windows_is_folder_in_use(path):
|
||||||
|
'''
|
||||||
|
Returns the path to a file that is used in another process in the specified
|
||||||
|
folder, or None if no such file exists. Note
|
||||||
|
that this function is not a guarantee. A file may well be opened in the
|
||||||
|
folder after this function returns. However, it is useful to handle the
|
||||||
|
common case of a sharing violation gracefully most of the time.
|
||||||
|
'''
|
||||||
|
if isbytestring(path): path = path.decode(filesystem_encoding)
|
||||||
|
for x in os.listdir(path):
|
||||||
|
f = os.path.join(path, x)
|
||||||
|
if windows_is_file_opened(f):
|
||||||
|
return f
|
||||||
|
return None
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user