This commit is contained in:
Kovid Goyal 2020-11-02 18:11:59 +05:30
parent 786f3e963e
commit 0f590b1e20
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 19 additions and 20 deletions

View File

@ -10,15 +10,13 @@ import os
import re import re
import shutil import shutil
import sys import sys
import time
import unicodedata import unicodedata
import uuid import uuid
from collections import defaultdict from collections import defaultdict
from css_parser import getUrls, replaceUrls
from io import BytesIO from io import BytesIO
from itertools import count from itertools import count
from css_parser import getUrls, replaceUrls
from calibre import CurrentDir, walk from calibre import CurrentDir, walk
from calibre.constants import iswindows from calibre.constants import iswindows
from calibre.customize.ui import plugin_for_input_format, plugin_for_output_format from calibre.customize.ui import plugin_for_input_format, plugin_for_output_format
@ -48,7 +46,7 @@ from calibre.ebooks.oeb.polish.utils import (
CommentFinder, PositionFinder, guess_type, parse_css CommentFinder, PositionFinder, guess_type, parse_css
) )
from calibre.ptempfile import PersistentTemporaryDirectory, PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryDirectory, PersistentTemporaryFile
from calibre.utils.filenames import hardlink_file, nlinks_file from calibre.utils.filenames import hardlink_file, nlinks_file, retry_on_fail
from calibre.utils.ipc.simple_worker import WorkerError, fork_job from calibre.utils.ipc.simple_worker import WorkerError, fork_job
from calibre.utils.logging import default_log from calibre.utils.logging import default_log
from calibre.utils.xml_parse import safe_xml_fromstring from calibre.utils.xml_parse import safe_xml_fromstring
@ -1057,12 +1055,9 @@ class Container(ContainerBase): # {{{
# Decouple this file from its links # Decouple this file from its links
temp = path + 'xxx' temp = path + 'xxx'
shutil.copyfile(path, temp) shutil.copyfile(path, temp)
try: if iswindows:
os.unlink(path) retry_on_fail(os.unlink, path)
except EnvironmentError: else:
if not iswindows:
raise
time.sleep(1) # Wait for whatever has locked the file to release it
os.unlink(path) os.unlink(path)
os.rename(temp, path) os.rename(temp, path)
return path return path

View File

@ -466,21 +466,25 @@ if iswindows:
move_file(a, b) move_file(a, b)
def retry_on_fail(func, *args, count=10, sleep_time=0.2):
for i in range(count):
try:
func(*args)
break
except OSError:
if i > count - 2:
raise
# Try the operation repeatedly in case something like a virus
# scanner has opened one of the files (I love windows)
time.sleep(sleep_time)
def atomic_rename(oldpath, newpath): def atomic_rename(oldpath, newpath):
'''Replace the file newpath with the file oldpath. Can fail if the files '''Replace the file newpath with the file oldpath. Can fail if the files
are on different volumes. If succeeds, guaranteed to be atomic. newpath may are on different volumes. If succeeds, guaranteed to be atomic. newpath may
or may not exist. If it exists, it is replaced. ''' or may not exist. If it exists, it is replaced. '''
if iswindows: if iswindows:
for i in range(10): retry_on_fail(rename_file, oldpath, newpath)
try:
rename_file(oldpath, newpath)
break
except Exception:
if i > 8:
raise
# Try the rename repeatedly in case something like a virus
# scanner has opened one of the files (I love windows)
time.sleep(1)
else: else:
os.rename(oldpath, newpath) os.rename(oldpath, newpath)