Merged revisions 72981 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r72981 | tarek.ziade | 2009-05-28 14:53:54 +0200 (Thu, 28 May 2009) | 1 line
Fixed #6048: Distutils uses the tarfile module instead of the tar command now
........
diff --git a/Lib/distutils/archive_util.py b/Lib/distutils/archive_util.py
index 08a9e56..a568854 100644
--- a/Lib/distutils/archive_util.py
+++ b/Lib/distutils/archive_util.py
@@ -6,6 +6,9 @@
__revision__ = "$Id$"
import os
+from warnings import warn
+import sys
+
from distutils.errors import DistutilsExecError
from distutils.spawn import spawn
from distutils.dir_util import mkpath
@@ -22,36 +25,45 @@
the appropriate compression extension (".gz", ".bz2" or ".Z").
Returns the output filename.
"""
- # XXX GNU tar 1.13 has a nifty option to add a prefix directory.
- # It's pretty new, though, so we certainly can't require it --
- # but it would be nice to take advantage of it to skip the
- # "create a tree of hardlinks" step! (Would also be nice to
- # detect GNU tar to use its 'z' option and save a step.)
-
- compress_ext = {'gzip': ".gz",
- 'bzip2': '.bz2',
- 'compress': ".Z" }
+ tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', None: '', 'compress': ''}
+ compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'compress': '.Z'}
# flags for compression program, each element of list will be an argument
- compress_flags = {'gzip': ["-f9"],
- 'compress': ["-f"],
- 'bzip2': ['-f9']}
-
if compress is not None and compress not in compress_ext.keys():
raise ValueError(
- "bad value for 'compress': must be None, 'gzip', or 'compress'")
+ "bad value for 'compress': must be None, 'gzip', 'bzip2' "
+ "or 'compress'")
- archive_name = base_name + ".tar"
+ archive_name = base_name + '.tar'
+ if compress != 'compress':
+ archive_name += compress_ext.get(compress, '')
+
mkpath(os.path.dirname(archive_name), dry_run=dry_run)
- cmd = ["tar", "-cf", archive_name, base_dir]
- spawn(cmd, dry_run=dry_run)
- if compress:
- spawn([compress] + compress_flags[compress] + [archive_name],
- dry_run=dry_run)
- return archive_name + compress_ext[compress]
- else:
- return archive_name
+ # creating the tarball
+ import tarfile # late import so Python build itself doesn't break
+
+ log.info('Creating tar archive')
+ if not dry_run:
+ tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
+ try:
+ tar.add(base_dir)
+ finally:
+ tar.close()
+
+ # compression using `compress`
+ if compress == 'compress':
+ warn("'compress' will be deprecated.", PendingDeprecationWarning)
+ # the option varies depending on the platform
+ compressed_name = archive_name + compress_ext[compress]
+ if sys.platform == 'win32':
+ cmd = [compress, archive_name, compressed_name]
+ else:
+ cmd = [compress, '-f', archive_name]
+ spawn(cmd, dry_run=dry_run)
+ return compressed_name
+
+ return archive_name
def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
"""Create a zip file from all the files under 'base_dir'.
diff --git a/Lib/distutils/tests/test_archive_util.py b/Lib/distutils/tests/test_archive_util.py
index cabb55b..5db9a5d 100644
--- a/Lib/distutils/tests/test_archive_util.py
+++ b/Lib/distutils/tests/test_archive_util.py
@@ -3,12 +3,15 @@
import unittest
import os
+import tarfile
from os.path import splitdrive
+import warnings
from distutils.archive_util import (check_archive_formats, make_tarball,
make_zipfile, make_archive)
-from distutils.spawn import find_executable
+from distutils.spawn import find_executable, spawn
from distutils.tests import support
+from test.support import check_warnings
try:
import zipfile
@@ -19,12 +22,13 @@
class ArchiveUtilTestCase(support.TempdirManager,
unittest.TestCase):
- @unittest.skipUnless(find_executable('tar'), 'Need the tar command to run')
def test_make_tarball(self):
# creating something to tar
tmpdir = self.mkdtemp()
self.write_file([tmpdir, 'file1'], 'xxx')
self.write_file([tmpdir, 'file2'], 'xxx')
+ os.mkdir(os.path.join(tmpdir, 'sub'))
+ self.write_file([tmpdir, 'sub', 'file3'], 'xxx')
tmpdir2 = self.mkdtemp()
unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
@@ -55,6 +59,111 @@
tarball = base_name + '.tar'
self.assert_(os.path.exists(tarball))
+ def _tarinfo(self, path):
+ tar = tarfile.open(path)
+ try:
+ names = tar.getnames()
+ names.sort()
+ return tuple(names)
+ finally:
+ tar.close()
+
+ def _create_files(self):
+ # creating something to tar
+ tmpdir = self.mkdtemp()
+ dist = os.path.join(tmpdir, 'dist')
+ os.mkdir(dist)
+ self.write_file([dist, 'file1'], 'xxx')
+ self.write_file([dist, 'file2'], 'xxx')
+ os.mkdir(os.path.join(dist, 'sub'))
+ self.write_file([dist, 'sub', 'file3'], 'xxx')
+ os.mkdir(os.path.join(dist, 'sub2'))
+ tmpdir2 = self.mkdtemp()
+ base_name = os.path.join(tmpdir2, 'archive')
+ return tmpdir, tmpdir2, base_name
+
+ @unittest.skipUnless(find_executable('tar'), 'Need the tar command to run')
+ def test_tarfile_vs_tar(self):
+ tmpdir, tmpdir2, base_name = self._create_files()
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ make_tarball(base_name, 'dist')
+ finally:
+ os.chdir(old_dir)
+
+ # check if the compressed tarball was created
+ tarball = base_name + '.tar.gz'
+ self.assert_(os.path.exists(tarball))
+
+ # now create another tarball using `tar`
+ tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
+ cmd = ['tar', '-czf', 'archive2.tar.gz', 'dist']
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ spawn(cmd)
+ finally:
+ os.chdir(old_dir)
+
+ self.assert_(os.path.exists(tarball2))
+ # let's compare both tarballs
+ self.assertEquals(self._tarinfo(tarball), self._tarinfo(tarball2))
+
+ # trying an uncompressed one
+ base_name = os.path.join(tmpdir2, 'archive')
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ make_tarball(base_name, 'dist', compress=None)
+ finally:
+ os.chdir(old_dir)
+ tarball = base_name + '.tar'
+ self.assert_(os.path.exists(tarball))
+
+ # now for a dry_run
+ base_name = os.path.join(tmpdir2, 'archive')
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ make_tarball(base_name, 'dist', compress=None, dry_run=True)
+ finally:
+ os.chdir(old_dir)
+ tarball = base_name + '.tar'
+ self.assert_(os.path.exists(tarball))
+
+ @unittest.skipUnless(find_executable('compress'),
+ 'The compress program is required')
+ def test_compress_deprecated(self):
+ tmpdir, tmpdir2, base_name = self._create_files()
+
+ # using compress and testing the PendingDeprecationWarning
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ with check_warnings() as w:
+ warnings.simplefilter("always")
+ make_tarball(base_name, 'dist', compress='compress')
+ finally:
+ os.chdir(old_dir)
+ tarball = base_name + '.tar.Z'
+ self.assert_(os.path.exists(tarball))
+ self.assertEquals(len(w.warnings), 1)
+
+ # same test with dry_run
+ os.remove(tarball)
+ old_dir = os.getcwd()
+ os.chdir(tmpdir)
+ try:
+ with check_warnings() as w:
+ warnings.simplefilter("always")
+ make_tarball(base_name, 'dist', compress='compress',
+ dry_run=True)
+ finally:
+ os.chdir(old_dir)
+ self.assert_(not os.path.exists(tarball))
+ self.assertEquals(len(w.warnings), 1)
+
@unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
def test_make_zipfile(self):
# creating something to tar
diff --git a/Misc/NEWS b/Misc/NEWS
index d111709..8a01b21 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -684,6 +684,8 @@
Library
-------
+- Issue #6048: Now Distutils uses the tarfile module in archive_util.
+
- Issue #6062: In distutils, fixed the package option of build_ext. Feedback
and tests on pywin32 by Tim Golden.