idf_tools.py: add workaround for PermissionError in os.rename

Closes https://github.com/espressif/esp-idf/issues/4063
Closes https://github.com/espressif/esp-idf/issues/3819
pull/4139/head
Ivan Grokhotkov 2019-09-23 06:01:09 +02:00
rodzic 81ffc87371
commit 3bbb758bc5
1 zmienionych plików z 30 dodań i 3 usunięć

Wyświetl plik

@ -61,6 +61,12 @@ try:
except ImportError:
from urllib import urlretrieve
try:
from exceptions import WindowsError
except ImportError:
class WindowsError(OSError):
pass
TOOLS_FILE = 'tools/tools.json'
TOOLS_SCHEMA_FILE = 'tools/tools_schema.json'
@ -254,13 +260,34 @@ def unpack(filename, destination):
archive_obj.extractall(destination)
# Sometimes renaming a directory on Windows (randomly?) causes a PermissionError.
# This is confirmed to be a workaround:
# https://github.com/espressif/esp-idf/issues/3819#issuecomment-515167118
# https://github.com/espressif/esp-idf/issues/4063#issuecomment-531490140
# https://stackoverflow.com/a/43046729
def rename_with_retry(path_from, path_to):
if sys.platform.startswith('win'):
retry_count = 100
else:
retry_count = 1
for retry in range(retry_count):
try:
os.rename(path_from, path_to)
return
except (OSError, WindowsError): # WindowsError until Python 3.3, then OSError
if retry == retry_count - 1:
raise
warn('Rename {} to {} failed, retrying...'.format(path_from, path_to))
def strip_container_dirs(path, levels):
assert levels > 0
# move the original directory out of the way (add a .tmp suffix)
tmp_path = path + '.tmp'
if os.path.exists(tmp_path):
shutil.rmtree(tmp_path)
os.rename(path, tmp_path)
rename_with_retry(path, tmp_path)
os.mkdir(path)
base_path = tmp_path
# walk given number of levels down
@ -276,7 +303,7 @@ def strip_container_dirs(path, levels):
for name in contents:
move_from = os.path.join(base_path, name)
move_to = os.path.join(path, name)
os.rename(move_from, move_to)
rename_with_retry(move_from, move_to)
shutil.rmtree(tmp_path)
@ -544,7 +571,7 @@ class IDFTool(object):
if not self.check_download_file(download_obj, local_temp_path):
warn('Failed to download file {}'.format(local_temp_path))
continue
os.rename(local_temp_path, local_path)
rename_with_retry(local_temp_path, local_path)
downloaded = True
break
if not downloaded: