archive: Handle possible conflicts if upper directories cannot be created
Installation fails when overriding a file with a directory. With this change, Pisi will remove the old files before creating the upper directories.
This commit is contained in:
+36
-1
@@ -15,6 +15,7 @@
|
|||||||
# standard library modules
|
# standard library modules
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
|
import errno
|
||||||
import shutil
|
import shutil
|
||||||
import tarfile
|
import tarfile
|
||||||
import zipfile
|
import zipfile
|
||||||
@@ -339,7 +340,41 @@ class ArchiveTar(ArchiveBase):
|
|||||||
# If fails, try to remove it
|
# If fails, try to remove it
|
||||||
shutil.rmtree(tarinfo.name)
|
shutil.rmtree(tarinfo.name)
|
||||||
|
|
||||||
self.tar.extract(tarinfo)
|
try:
|
||||||
|
self.tar.extract(tarinfo)
|
||||||
|
except OSError, e:
|
||||||
|
# Handle the case where an upper directory cannot
|
||||||
|
# be created because of a conflict with an existing
|
||||||
|
# regular file or symlink. In this case, remove
|
||||||
|
# the old file and retry extracting.
|
||||||
|
|
||||||
|
if e.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# For the path "a/b/c", upper_dirs will be ["a", "a/b"].
|
||||||
|
upper_dirs = []
|
||||||
|
head, tail = os.path.split(tarinfo.name)
|
||||||
|
|
||||||
|
while head and tail:
|
||||||
|
upper_dirs.insert(0, head)
|
||||||
|
head, tail = os.path.split(head)
|
||||||
|
|
||||||
|
for path in upper_dirs:
|
||||||
|
if not os.path.lexists(path):
|
||||||
|
break
|
||||||
|
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
# A file with the same name exists.
|
||||||
|
# Remove the existing file.
|
||||||
|
os.remove(path)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# No conflicts detected! This is probably not the case
|
||||||
|
# mentioned here. Raise the same exception.
|
||||||
|
raise
|
||||||
|
|
||||||
|
# Try to extract again.
|
||||||
|
self.tar.extract(tarinfo)
|
||||||
|
|
||||||
# tarfile.extract does not honor umask. It must be honored
|
# tarfile.extract does not honor umask. It must be honored
|
||||||
# explicitly. See --no-same-permissions option of tar(1),
|
# explicitly. See --no-same-permissions option of tar(1),
|
||||||
|
|||||||
Reference in New Issue
Block a user