1 """Tests for distutils.archive_util.""" 2 __revision__ = "$Id$" 3 4 import unittest 5 import os 6 import tarfile 7 from os.path import splitdrive 8 import warnings 9 10 from distutils.archive_util import (check_archive_formats, make_tarball, 11 make_zipfile, make_archive, 12 ARCHIVE_FORMATS) 13 from distutils.spawn import find_executable, spawn 14 from distutils.tests import support 15 from test.test_support import check_warnings, run_unittest 16 17 try: 18 import grp 19 import pwd 20 UID_GID_SUPPORT = True 21 except ImportError: 22 UID_GID_SUPPORT = False 23 24 try: 25 import zipfile 26 ZIP_SUPPORT = True 27 except ImportError: 28 ZIP_SUPPORT = find_executable('zip') 29 30 # some tests will fail if zlib is not available 31 try: 32 import zlib 33 except ImportError: 34 zlib = None 35 36 37 class ArchiveUtilTestCase(support.TempdirManager, 38 support.LoggingSilencer, 39 unittest.TestCase): 40 41 @unittest.skipUnless(zlib, "requires zlib") 42 def test_make_tarball(self): 43 # creating something to tar 44 tmpdir = self.mkdtemp() 45 self.write_file([tmpdir, 'file1'], 'xxx') 46 self.write_file([tmpdir, 'file2'], 'xxx') 47 os.mkdir(os.path.join(tmpdir, 'sub')) 48 self.write_file([tmpdir, 'sub', 'file3'], 'xxx') 49 50 tmpdir2 = self.mkdtemp() 51 unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0], 52 "source and target should be on same drive") 53 54 base_name = os.path.join(tmpdir2, 'archive') 55 56 # working with relative paths to avoid tar warnings 57 old_dir = os.getcwd() 58 os.chdir(tmpdir) 59 try: 60 make_tarball(splitdrive(base_name)[1], '.') 61 finally: 62 os.chdir(old_dir) 63 64 # check if the compressed tarball was created 65 tarball = base_name + '.tar.gz' 66 self.assertTrue(os.path.exists(tarball)) 67 68 # trying an uncompressed one 69 base_name = os.path.join(tmpdir2, 'archive') 70 old_dir = os.getcwd() 71 os.chdir(tmpdir) 72 try: 73 make_tarball(splitdrive(base_name)[1], '.', compress=None) 74 finally: 75 os.chdir(old_dir) 76 tarball = base_name + '.tar' 77 self.assertTrue(os.path.exists(tarball)) 78 79 def _tarinfo(self, path): 80 tar = tarfile.open(path) 81 try: 82 names = tar.getnames() 83 names.sort() 84 return tuple(names) 85 finally: 86 tar.close() 87 88 def _create_files(self): 89 # creating something to tar 90 tmpdir = self.mkdtemp() 91 dist = os.path.join(tmpdir, 'dist') 92 os.mkdir(dist) 93 self.write_file([dist, 'file1'], 'xxx') 94 self.write_file([dist, 'file2'], 'xxx') 95 os.mkdir(os.path.join(dist, 'sub')) 96 self.write_file([dist, 'sub', 'file3'], 'xxx') 97 os.mkdir(os.path.join(dist, 'sub2')) 98 tmpdir2 = self.mkdtemp() 99 base_name = os.path.join(tmpdir2, 'archive') 100 return tmpdir, tmpdir2, base_name 101 102 @unittest.skipUnless(zlib, "Requires zlib") 103 @unittest.skipUnless(find_executable('tar') and find_executable('gzip'), 104 'Need the tar command to run') 105 def test_tarfile_vs_tar(self): 106 tmpdir, tmpdir2, base_name = self._create_files() 107 old_dir = os.getcwd() 108 os.chdir(tmpdir) 109 try: 110 make_tarball(base_name, 'dist') 111 finally: 112 os.chdir(old_dir) 113 114 # check if the compressed tarball was created 115 tarball = base_name + '.tar.gz' 116 self.assertTrue(os.path.exists(tarball)) 117 118 # now create another tarball using `tar` 119 tarball2 = os.path.join(tmpdir, 'archive2.tar.gz') 120 tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist'] 121 gzip_cmd = ['gzip', '-f9', 'archive2.tar'] 122 old_dir = os.getcwd() 123 os.chdir(tmpdir) 124 try: 125 spawn(tar_cmd) 126 spawn(gzip_cmd) 127 finally: 128 os.chdir(old_dir) 129 130 self.assertTrue(os.path.exists(tarball2)) 131 # let's compare both tarballs 132 self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2)) 133 134 # trying an uncompressed one 135 base_name = os.path.join(tmpdir2, 'archive') 136 old_dir = os.getcwd() 137 os.chdir(tmpdir) 138 try: 139 make_tarball(base_name, 'dist', compress=None) 140 finally: 141 os.chdir(old_dir) 142 tarball = base_name + '.tar' 143 self.assertTrue(os.path.exists(tarball)) 144 145 # now for a dry_run 146 base_name = os.path.join(tmpdir2, 'archive') 147 old_dir = os.getcwd() 148 os.chdir(tmpdir) 149 try: 150 make_tarball(base_name, 'dist', compress=None, dry_run=True) 151 finally: 152 os.chdir(old_dir) 153 tarball = base_name + '.tar' 154 self.assertTrue(os.path.exists(tarball)) 155 156 @unittest.skipUnless(find_executable('compress'), 157 'The compress program is required') 158 def test_compress_deprecated(self): 159 tmpdir, tmpdir2, base_name = self._create_files() 160 161 # using compress and testing the PendingDeprecationWarning 162 old_dir = os.getcwd() 163 os.chdir(tmpdir) 164 try: 165 with check_warnings() as w: 166 warnings.simplefilter("always") 167 make_tarball(base_name, 'dist', compress='compress') 168 finally: 169 os.chdir(old_dir) 170 tarball = base_name + '.tar.Z' 171 self.assertTrue(os.path.exists(tarball)) 172 self.assertEqual(len(w.warnings), 1) 173 174 # same test with dry_run 175 os.remove(tarball) 176 old_dir = os.getcwd() 177 os.chdir(tmpdir) 178 try: 179 with check_warnings() as w: 180 warnings.simplefilter("always") 181 make_tarball(base_name, 'dist', compress='compress', 182 dry_run=True) 183 finally: 184 os.chdir(old_dir) 185 self.assertTrue(not os.path.exists(tarball)) 186 self.assertEqual(len(w.warnings), 1) 187 188 @unittest.skipUnless(zlib, "Requires zlib") 189 @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run') 190 def test_make_zipfile(self): 191 # creating something to tar 192 tmpdir = self.mkdtemp() 193 self.write_file([tmpdir, 'file1'], 'xxx') 194 self.write_file([tmpdir, 'file2'], 'xxx') 195 196 tmpdir2 = self.mkdtemp() 197 base_name = os.path.join(tmpdir2, 'archive') 198 make_zipfile(base_name, tmpdir) 199 200 # check if the compressed tarball was created 201 tarball = base_name + '.zip' 202 203 def test_check_archive_formats(self): 204 self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']), 205 'xxx') 206 self.assertEqual(check_archive_formats(['gztar', 'zip']), None) 207 208 def test_make_archive(self): 209 tmpdir = self.mkdtemp() 210 base_name = os.path.join(tmpdir, 'archive') 211 self.assertRaises(ValueError, make_archive, base_name, 'xxx') 212 213 @unittest.skipUnless(zlib, "Requires zlib") 214 def test_make_archive_owner_group(self): 215 # testing make_archive with owner and group, with various combinations 216 # this works even if there's not gid/uid support 217 if UID_GID_SUPPORT: 218 group = grp.getgrgid(0)[0] 219 owner = pwd.getpwuid(0)[0] 220 else: 221 group = owner = 'root' 222 223 base_dir, root_dir, base_name = self._create_files() 224 base_name = os.path.join(self.mkdtemp() , 'archive') 225 res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner, 226 group=group) 227 self.assertTrue(os.path.exists(res)) 228 229 res = make_archive(base_name, 'zip', root_dir, base_dir) 230 self.assertTrue(os.path.exists(res)) 231 232 res = make_archive(base_name, 'tar', root_dir, base_dir, 233 owner=owner, group=group) 234 self.assertTrue(os.path.exists(res)) 235 236 res = make_archive(base_name, 'tar', root_dir, base_dir, 237 owner='kjhkjhkjg', group='oihohoh') 238 self.assertTrue(os.path.exists(res)) 239 240 @unittest.skipUnless(zlib, "Requires zlib") 241 @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support") 242 def test_tarfile_root_owner(self): 243 tmpdir, tmpdir2, base_name = self._create_files() 244 old_dir = os.getcwd() 245 os.chdir(tmpdir) 246 group = grp.getgrgid(0)[0] 247 owner = pwd.getpwuid(0)[0] 248 try: 249 archive_name = make_tarball(base_name, 'dist', compress=None, 250 owner=owner, group=group) 251 finally: 252 os.chdir(old_dir) 253 254 # check if the compressed tarball was created 255 self.assertTrue(os.path.exists(archive_name)) 256 257 # now checks the rights 258 archive = tarfile.open(archive_name) 259 try: 260 for member in archive.getmembers(): 261 self.assertEqual(member.uid, 0) 262 self.assertEqual(member.gid, 0) 263 finally: 264 archive.close() 265 266 def test_make_archive_cwd(self): 267 current_dir = os.getcwd() 268 def _breaks(*args, **kw): 269 raise RuntimeError() 270 ARCHIVE_FORMATS['xxx'] = (_breaks, [], 'xxx file') 271 try: 272 try: 273 make_archive('xxx', 'xxx', root_dir=self.mkdtemp()) 274 except: 275 pass 276 self.assertEqual(os.getcwd(), current_dir) 277 finally: 278 del ARCHIVE_FORMATS['xxx'] 279 280 def test_suite(): 281 return unittest.makeSuite(ArchiveUtilTestCase) 282 283 if __name__ == "__main__": 284 run_unittest(test_suite()) 285