aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools/archive_util.py
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/archive_util.py')
-rwxr-xr-xsetuptools/archive_util.py94
1 files changed, 70 insertions, 24 deletions
diff --git a/setuptools/archive_util.py b/setuptools/archive_util.py
index d24c6c13..1109f346 100755
--- a/setuptools/archive_util.py
+++ b/setuptools/archive_util.py
@@ -3,10 +3,10 @@
__all__ = [
"unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter",
- "UnrecognizedFormat", "extraction_drivers"
+ "UnrecognizedFormat", "extraction_drivers", "unpack_directory",
]
-import zipfile, tarfile, os
+import zipfile, tarfile, os, shutil, posixpath
from pkg_resources import ensure_directory
from distutils.errors import DistutilsError
@@ -80,6 +80,47 @@ def unpack_archive(filename, extract_dir, progress_filter=default_filter,
+def unpack_directory(filename, extract_dir, progress_filter=default_filter):
+ """"Unpack" a directory, using the same interface as for archives
+
+ Raises ``UnrecognizedFormat`` if `filename` is not a directory
+ """
+ if not os.path.isdir(filename):
+ raise UnrecognizedFormat("%s is not a directory" % (filename,))
+
+ paths = {filename:('',extract_dir)}
+ for base, dirs, files in os.walk(filename):
+ src,dst = paths[base]
+ for d in dirs:
+ paths[os.path.join(base,d)] = src+d+'/', os.path.join(dst,d)
+ for f in files:
+ name = src+f
+ target = os.path.join(dst,f)
+ target = progress_filter(src+f, target)
+ if not target:
+ continue # skip non-files
+ ensure_directory(target)
+ f = os.path.join(base,f)
+ shutil.copyfile(f, target)
+ shutil.copystat(f, target)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
"""Unpack zip `filename` to `extract_dir`
@@ -97,7 +138,7 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
name = info.filename
# don't extract absolute paths or ones with .. in them
- if name.startswith('/') or '..' in name:
+ if name.startswith('/') or '..' in name.split('/'):
continue
target = os.path.join(extract_dir, *name.split('/'))
@@ -117,6 +158,9 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
finally:
f.close()
del data
+ unix_attributes = info.external_attr >> 16
+ if unix_attributes:
+ os.chmod(target, unix_attributes)
finally:
z.close()
@@ -128,37 +172,39 @@ def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):
by ``tarfile.open()``). See ``unpack_archive()`` for an explanation
of the `progress_filter` argument.
"""
-
try:
tarobj = tarfile.open(filename)
except tarfile.TarError:
raise UnrecognizedFormat(
"%s is not a compressed or uncompressed tar file" % (filename,)
)
-
try:
tarobj.chown = lambda *args: None # don't do any chowning!
for member in tarobj:
- if member.isfile() or member.isdir():
- name = member.name
- # don't extract absolute paths or ones with .. in them
- if not name.startswith('/') and '..' not in name:
- dst = os.path.join(extract_dir, *name.split('/'))
- dst = progress_filter(name, dst)
- if dst:
- if dst.endswith(os.sep):
- dst = dst[:-1]
- tarobj._extract_member(member,dst) # XXX Ugh
+ name = member.name
+ # don't extract absolute paths or ones with .. in them
+ if not name.startswith('/') and '..' not in name.split('/'):
+ prelim_dst = os.path.join(extract_dir, *name.split('/'))
+
+ # resolve any links and to extract the link targets as normal files
+ while member is not None and (member.islnk() or member.issym()):
+ linkpath = member.linkname
+ if member.issym():
+ linkpath = posixpath.join(posixpath.dirname(member.name), linkpath)
+ linkpath = posixpath.normpath(linkpath)
+ member = tarobj._getmember(linkpath)
+
+ if member is not None and (member.isfile() or member.isdir()):
+ final_dst = progress_filter(name, prelim_dst)
+ if final_dst:
+ if final_dst.endswith(os.sep):
+ final_dst = final_dst[:-1]
+ try:
+ tarobj._extract_member(member, final_dst) # XXX Ugh
+ except tarfile.ExtractError:
+ pass # chown/chmod/mkfifo/mknode/makedev failed
return True
finally:
tarobj.close()
-
-
-
-extraction_drivers = unpack_zipfile, unpack_tarfile
-
-
-
-
-
+extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile