blob: ed7c2cea69cbc75e8ee13c9c1b45223de8b50b72 [file] [log] [blame]
Jason R. Coombs042370e2011-12-26 10:15:15 -05001# -*- coding: utf-8 -*-
Tarek Ziadé6f826ed2009-05-17 12:04:57 +00002"""Tests for distutils.archive_util."""
Tarek Ziadé6dd6b612009-05-17 14:59:05 +00003__revision__ = "$Id$"
Tarek Ziadé6f826ed2009-05-17 12:04:57 +00004
5import unittest
6import os
Jason R. Coombs79e50c62011-12-28 11:42:22 -05007import sys
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +00008import tarfile
Tarek Ziadé07bbfcc2009-05-18 12:21:26 +00009from os.path import splitdrive
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +000010import warnings
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000011
12from distutils.archive_util import (check_archive_formats, make_tarball,
Tarek Ziadé672422a2009-10-24 13:29:44 +000013 make_zipfile, make_archive,
14 ARCHIVE_FORMATS)
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +000015from distutils.spawn import find_executable, spawn
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000016from distutils.tests import support
Éric Araujo54274ad2011-02-03 00:12:18 +000017from test.test_support import check_warnings, run_unittest
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000018
19try:
Tarek Ziadé1b486712009-10-02 23:49:48 +000020 import grp
21 import pwd
22 UID_GID_SUPPORT = True
23except ImportError:
24 UID_GID_SUPPORT = False
25
26try:
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000027 import zipfile
28 ZIP_SUPPORT = True
29except ImportError:
30 ZIP_SUPPORT = find_executable('zip')
31
Ezio Melotti1036a7f2009-09-12 14:43:43 +000032# some tests will fail if zlib is not available
33try:
34 import zlib
35except ImportError:
36 zlib = None
37
Jason R. Coombs79e50c62011-12-28 11:42:22 -050038def can_fs_encode(filename):
39 """
40 Return True if the filename can be saved in the file system.
41 """
42 if os.path.supports_unicode_filenames:
43 return True
44 try:
45 filename.encode(sys.getfilesystemencoding())
46 except UnicodeEncodeError:
47 return False
48 return True
49
Ezio Melotti1036a7f2009-09-12 14:43:43 +000050
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000051class ArchiveUtilTestCase(support.TempdirManager,
Tarek Ziadé460f6c82009-05-28 13:55:51 +000052 support.LoggingSilencer,
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000053 unittest.TestCase):
54
Tarek Ziadé1b486712009-10-02 23:49:48 +000055 @unittest.skipUnless(zlib, "requires zlib")
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000056 def test_make_tarball(self):
Jason R. Coombs042370e2011-12-26 10:15:15 -050057 self._make_tarball('archive')
58
59 def _make_tarball(self, target_name):
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000060 # creating something to tar
61 tmpdir = self.mkdtemp()
62 self.write_file([tmpdir, 'file1'], 'xxx')
63 self.write_file([tmpdir, 'file2'], 'xxx')
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +000064 os.mkdir(os.path.join(tmpdir, 'sub'))
65 self.write_file([tmpdir, 'sub', 'file3'], 'xxx')
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000066
67 tmpdir2 = self.mkdtemp()
Tarek Ziadé07bbfcc2009-05-18 12:21:26 +000068 unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
Tarek Ziadé1b486712009-10-02 23:49:48 +000069 "source and target should be on same drive")
Tarek Ziadé07bbfcc2009-05-18 12:21:26 +000070
Jason R. Coombs042370e2011-12-26 10:15:15 -050071 base_name = os.path.join(tmpdir2, target_name)
Tarek Ziadé6deb5742009-05-18 08:20:55 +000072
73 # working with relative paths to avoid tar warnings
74 old_dir = os.getcwd()
75 os.chdir(tmpdir)
76 try:
Tarek Ziadé07bbfcc2009-05-18 12:21:26 +000077 make_tarball(splitdrive(base_name)[1], '.')
Tarek Ziadé6deb5742009-05-18 08:20:55 +000078 finally:
79 os.chdir(old_dir)
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000080
81 # check if the compressed tarball was created
82 tarball = base_name + '.tar.gz'
Benjamin Peterson5c8da862009-06-30 22:57:08 +000083 self.assertTrue(os.path.exists(tarball))
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000084
85 # trying an uncompressed one
Jason R. Coombs042370e2011-12-26 10:15:15 -050086 base_name = os.path.join(tmpdir2, target_name)
Tarek Ziadé6deb5742009-05-18 08:20:55 +000087 old_dir = os.getcwd()
88 os.chdir(tmpdir)
89 try:
Tarek Ziadé07bbfcc2009-05-18 12:21:26 +000090 make_tarball(splitdrive(base_name)[1], '.', compress=None)
Tarek Ziadé6deb5742009-05-18 08:20:55 +000091 finally:
92 os.chdir(old_dir)
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000093 tarball = base_name + '.tar'
Benjamin Peterson5c8da862009-06-30 22:57:08 +000094 self.assertTrue(os.path.exists(tarball))
Tarek Ziadé6f826ed2009-05-17 12:04:57 +000095
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +000096 def _tarinfo(self, path):
97 tar = tarfile.open(path)
98 try:
99 names = tar.getnames()
100 names.sort()
101 return tuple(names)
102 finally:
103 tar.close()
104
105 def _create_files(self):
106 # creating something to tar
107 tmpdir = self.mkdtemp()
108 dist = os.path.join(tmpdir, 'dist')
109 os.mkdir(dist)
110 self.write_file([dist, 'file1'], 'xxx')
111 self.write_file([dist, 'file2'], 'xxx')
112 os.mkdir(os.path.join(dist, 'sub'))
113 self.write_file([dist, 'sub', 'file3'], 'xxx')
114 os.mkdir(os.path.join(dist, 'sub2'))
115 tmpdir2 = self.mkdtemp()
116 base_name = os.path.join(tmpdir2, 'archive')
117 return tmpdir, tmpdir2, base_name
118
Ezio Melotti1036a7f2009-09-12 14:43:43 +0000119 @unittest.skipUnless(zlib, "Requires zlib")
Tarek Ziadé460f6c82009-05-28 13:55:51 +0000120 @unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
121 'Need the tar command to run')
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000122 def test_tarfile_vs_tar(self):
123 tmpdir, tmpdir2, base_name = self._create_files()
124 old_dir = os.getcwd()
125 os.chdir(tmpdir)
126 try:
127 make_tarball(base_name, 'dist')
128 finally:
129 os.chdir(old_dir)
130
131 # check if the compressed tarball was created
132 tarball = base_name + '.tar.gz'
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000133 self.assertTrue(os.path.exists(tarball))
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000134
135 # now create another tarball using `tar`
136 tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
Tarek Ziadé460f6c82009-05-28 13:55:51 +0000137 tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist']
138 gzip_cmd = ['gzip', '-f9', 'archive2.tar']
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000139 old_dir = os.getcwd()
140 os.chdir(tmpdir)
141 try:
Tarek Ziadé460f6c82009-05-28 13:55:51 +0000142 spawn(tar_cmd)
143 spawn(gzip_cmd)
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000144 finally:
145 os.chdir(old_dir)
146
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000147 self.assertTrue(os.path.exists(tarball2))
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000148 # let's compare both tarballs
Ezio Melotti2623a372010-11-21 13:34:58 +0000149 self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2))
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000150
151 # trying an uncompressed one
152 base_name = os.path.join(tmpdir2, 'archive')
153 old_dir = os.getcwd()
154 os.chdir(tmpdir)
155 try:
156 make_tarball(base_name, 'dist', compress=None)
157 finally:
158 os.chdir(old_dir)
159 tarball = base_name + '.tar'
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000160 self.assertTrue(os.path.exists(tarball))
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000161
162 # now for a dry_run
163 base_name = os.path.join(tmpdir2, 'archive')
164 old_dir = os.getcwd()
165 os.chdir(tmpdir)
166 try:
167 make_tarball(base_name, 'dist', compress=None, dry_run=True)
168 finally:
169 os.chdir(old_dir)
170 tarball = base_name + '.tar'
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000171 self.assertTrue(os.path.exists(tarball))
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000172
173 @unittest.skipUnless(find_executable('compress'),
174 'The compress program is required')
175 def test_compress_deprecated(self):
176 tmpdir, tmpdir2, base_name = self._create_files()
177
178 # using compress and testing the PendingDeprecationWarning
179 old_dir = os.getcwd()
180 os.chdir(tmpdir)
181 try:
182 with check_warnings() as w:
183 warnings.simplefilter("always")
184 make_tarball(base_name, 'dist', compress='compress')
185 finally:
186 os.chdir(old_dir)
187 tarball = base_name + '.tar.Z'
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000188 self.assertTrue(os.path.exists(tarball))
Ezio Melotti2623a372010-11-21 13:34:58 +0000189 self.assertEqual(len(w.warnings), 1)
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000190
191 # same test with dry_run
192 os.remove(tarball)
193 old_dir = os.getcwd()
194 os.chdir(tmpdir)
195 try:
196 with check_warnings() as w:
197 warnings.simplefilter("always")
198 make_tarball(base_name, 'dist', compress='compress',
199 dry_run=True)
200 finally:
201 os.chdir(old_dir)
Serhiy Storchaka25a23ef2013-11-17 00:29:27 +0200202 self.assertFalse(os.path.exists(tarball))
Ezio Melotti2623a372010-11-21 13:34:58 +0000203 self.assertEqual(len(w.warnings), 1)
Tarek Ziadé9e5d2dc2009-05-28 12:53:54 +0000204
Ezio Melotti1036a7f2009-09-12 14:43:43 +0000205 @unittest.skipUnless(zlib, "Requires zlib")
Tarek Ziadé6f826ed2009-05-17 12:04:57 +0000206 @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
Tarek Ziadé6dd6b612009-05-17 14:59:05 +0000207 def test_make_zipfile(self):
Tarek Ziadé6f826ed2009-05-17 12:04:57 +0000208 # creating something to tar
209 tmpdir = self.mkdtemp()
210 self.write_file([tmpdir, 'file1'], 'xxx')
211 self.write_file([tmpdir, 'file2'], 'xxx')
212
213 tmpdir2 = self.mkdtemp()
214 base_name = os.path.join(tmpdir2, 'archive')
215 make_zipfile(base_name, tmpdir)
216
217 # check if the compressed tarball was created
218 tarball = base_name + '.zip'
219
220 def test_check_archive_formats(self):
Ezio Melotti2623a372010-11-21 13:34:58 +0000221 self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']),
222 'xxx')
223 self.assertEqual(check_archive_formats(['gztar', 'zip']), None)
Tarek Ziadé6f826ed2009-05-17 12:04:57 +0000224
225 def test_make_archive(self):
226 tmpdir = self.mkdtemp()
227 base_name = os.path.join(tmpdir, 'archive')
228 self.assertRaises(ValueError, make_archive, base_name, 'xxx')
229
Tarek Ziadé19e6f012009-10-16 23:04:16 +0000230 @unittest.skipUnless(zlib, "Requires zlib")
Tarek Ziadé1b486712009-10-02 23:49:48 +0000231 def test_make_archive_owner_group(self):
232 # testing make_archive with owner and group, with various combinations
233 # this works even if there's not gid/uid support
234 if UID_GID_SUPPORT:
235 group = grp.getgrgid(0)[0]
236 owner = pwd.getpwuid(0)[0]
237 else:
238 group = owner = 'root'
239
240 base_dir, root_dir, base_name = self._create_files()
241 base_name = os.path.join(self.mkdtemp() , 'archive')
242 res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner,
243 group=group)
244 self.assertTrue(os.path.exists(res))
245
246 res = make_archive(base_name, 'zip', root_dir, base_dir)
247 self.assertTrue(os.path.exists(res))
248
249 res = make_archive(base_name, 'tar', root_dir, base_dir,
250 owner=owner, group=group)
251 self.assertTrue(os.path.exists(res))
252
253 res = make_archive(base_name, 'tar', root_dir, base_dir,
254 owner='kjhkjhkjg', group='oihohoh')
255 self.assertTrue(os.path.exists(res))
256
257 @unittest.skipUnless(zlib, "Requires zlib")
258 @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
259 def test_tarfile_root_owner(self):
260 tmpdir, tmpdir2, base_name = self._create_files()
261 old_dir = os.getcwd()
262 os.chdir(tmpdir)
263 group = grp.getgrgid(0)[0]
264 owner = pwd.getpwuid(0)[0]
265 try:
266 archive_name = make_tarball(base_name, 'dist', compress=None,
267 owner=owner, group=group)
268 finally:
269 os.chdir(old_dir)
270
271 # check if the compressed tarball was created
272 self.assertTrue(os.path.exists(archive_name))
273
274 # now checks the rights
275 archive = tarfile.open(archive_name)
276 try:
277 for member in archive.getmembers():
Ezio Melotti2623a372010-11-21 13:34:58 +0000278 self.assertEqual(member.uid, 0)
279 self.assertEqual(member.gid, 0)
Tarek Ziadé1b486712009-10-02 23:49:48 +0000280 finally:
281 archive.close()
282
Tarek Ziadé672422a2009-10-24 13:29:44 +0000283 def test_make_archive_cwd(self):
284 current_dir = os.getcwd()
285 def _breaks(*args, **kw):
286 raise RuntimeError()
287 ARCHIVE_FORMATS['xxx'] = (_breaks, [], 'xxx file')
288 try:
289 try:
290 make_archive('xxx', 'xxx', root_dir=self.mkdtemp())
291 except:
292 pass
Ezio Melotti2623a372010-11-21 13:34:58 +0000293 self.assertEqual(os.getcwd(), current_dir)
Tarek Ziadé672422a2009-10-24 13:29:44 +0000294 finally:
295 del ARCHIVE_FORMATS['xxx']
296
Jason R. Coombs042370e2011-12-26 10:15:15 -0500297 @unittest.skipUnless(zlib, "requires zlib")
298 def test_make_tarball_unicode(self):
299 """
300 Mirror test_make_tarball, except filename is unicode.
301 """
302 self._make_tarball(u'archive')
303
304 @unittest.skipUnless(zlib, "requires zlib")
Jason R. Coombs79e50c62011-12-28 11:42:22 -0500305 @unittest.skipUnless(can_fs_encode(u'årchiv'),
306 'File system cannot handle this filename')
Jason R. Coombs042370e2011-12-26 10:15:15 -0500307 def test_make_tarball_unicode_latin1(self):
308 """
309 Mirror test_make_tarball, except filename is unicode and contains
310 latin characters.
311 """
312 self._make_tarball(u'årchiv') # note this isn't a real word
313
314 @unittest.skipUnless(zlib, "requires zlib")
Jason R. Coombs79e50c62011-12-28 11:42:22 -0500315 @unittest.skipUnless(can_fs_encode(u'のアーカイブ'),
316 'File system cannot handle this filename')
Jason R. Coombs042370e2011-12-26 10:15:15 -0500317 def test_make_tarball_unicode_extended(self):
318 """
319 Mirror test_make_tarball, except filename is unicode and contains
320 characters outside the latin charset.
321 """
322 self._make_tarball(u'のアーカイブ') # japanese for archive
323
Tarek Ziadé6f826ed2009-05-17 12:04:57 +0000324def test_suite():
325 return unittest.makeSuite(ArchiveUtilTestCase)
326
327if __name__ == "__main__":
Éric Araujo54274ad2011-02-03 00:12:18 +0000328 run_unittest(test_suite())