Merged revisions 68885 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r68885 | martin.v.loewis | 2009-01-24 15:00:33 +0100 (Sa, 24 Jan 2009) | 3 lines

  Issue #4710: Extract directories properly in the zipfile module;
  allow adding directories to a zipfile.
........
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index c67bd5d..a54a354 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -4,7 +4,7 @@
 XXX references to utf-8 need further investigation.
 """
 import struct, os, time, sys, shutil
-import binascii, io
+import binascii, io, stat
 
 try:
     import zlib # We may need its compression method
@@ -959,11 +959,11 @@
         """
         # build the destination pathname, replacing
         # forward slashes to platform specific separators.
-        if targetpath[-1:] == "/":
+        if targetpath[-1:] in (os.path.sep, os.path.altsep):
             targetpath = targetpath[:-1]
 
         # don't include leading "/" from file name if present
-        if os.path.isabs(member.filename):
+        if member.filename[0] == '/':
             targetpath = os.path.join(targetpath, member.filename[1:])
         else:
             targetpath = os.path.join(targetpath, member.filename)
@@ -975,6 +975,10 @@
         if upperdirs and not os.path.exists(upperdirs):
             os.makedirs(upperdirs)
 
+        if member.filename[-1] == '/':
+            os.mkdir(targetpath)
+            return targetpath
+
         source = self.open(member, pwd=pwd)
         target = open(targetpath, "wb")
         shutil.copyfileobj(source, target)
@@ -1014,6 +1018,7 @@
                   "Attempt to write to ZIP archive that was already closed")
 
         st = os.stat(filename)
+        isdir = stat.S_ISDIR(st.st_mode)
         mtime = time.localtime(st.st_mtime)
         date_time = mtime[0:6]
         # Create ZipInfo instance to store file information
@@ -1022,6 +1027,8 @@
         arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
         while arcname[0] in (os.sep, os.altsep):
             arcname = arcname[1:]
+        if isdir:
+            arcname += '/'
         zinfo = ZipInfo(arcname, date_time)
         zinfo.external_attr = (st[0] & 0xFFFF) << 16      # Unix attributes
         if compress_type is None:
@@ -1035,6 +1042,16 @@
 
         self._writecheck(zinfo)
         self._didModify = True
+
+        if isdir:
+            zinfo.file_size = 0
+            zinfo.compress_size = 0
+            zinfo.CRC = 0
+            self.filelist.append(zinfo)
+            self.NameToInfo[zinfo.filename] = zinfo
+            self.fp.write(zinfo.FileHeader())
+            return
+
         fp = io.open(filename, "rb")
         # Must overwrite CRC and sizes with correct data later
         zinfo.CRC = CRC = 0