~abentley/bzrtools/bzrtools.dev

477 by Aaron Bentley
split out upstream_import test cases
1
import os
2
from StringIO import StringIO
488 by Aaron Bentley
Fix tests for importing directories
3
from shutil import rmtree, copy2, copytree
477 by Aaron Bentley
split out upstream_import test cases
4
import tarfile
488 by Aaron Bentley
Fix tests for importing directories
5
import tempfile
477 by Aaron Bentley
split out upstream_import test cases
6
from unittest import makeSuite
7
768 by Aaron Bentley
Fix non-ascii tarball handling
8
from bzrlib import (
9
    osutils,
10
    revision as _mod_revision,
11
    transform
12
    )
477 by Aaron Bentley
split out upstream_import test cases
13
from bzrlib.bzrdir import BzrDir
768 by Aaron Bentley
Fix non-ascii tarball handling
14
from bzrlib.export.tar_exporter import export_tarball
772 by Aaron Bentley
Better handling of compound tar names.
15
from bzrlib.plugins.bzrtools import errors
514 by Aaron Bentley
Fix imports
16
from bzrlib.plugins.bzrtools.upstream_import import (
17
    common_directory,
772 by Aaron Bentley
Better handling of compound tar names.
18
    get_archive_type,
517.1.3 by Aaron Bentley
Handle broken python tar implementations
19
    import_archive,
514 by Aaron Bentley
Fix imports
20
    import_tar,
21
    import_zip,
22
    import_dir,
703 by Aaron Bentley
Fix import with Python 2.6
23
    top_path,
531.2.2 by Charlie Shepherd
Remove all trailing whitespace
24
    ZipFileWrapper,
514 by Aaron Bentley
Fix imports
25
)
768 by Aaron Bentley
Fix non-ascii tarball handling
26
from bzrlib.tests import (
27
    TestCaseInTempDir,
28
    TestCaseWithTransport,
769.1.1 by Jelmer Vernooij
Skip test_nonascii_paths on platforms that don't support unicode paths.
29
    UnicodeFilenameFeature,
768 by Aaron Bentley
Fix non-ascii tarball handling
30
    )
477 by Aaron Bentley
split out upstream_import test cases
31
517.1.3 by Aaron Bentley
Handle broken python tar implementations
32
33
def import_tar_broken(tree, tar_input):
34
    """
35
    Import a tarfile with names that that end in //, e.g. Feisty Python 2.5
36
    """
37
    tar_file = tarfile.open('lala', 'r', tar_input)
38
    for member in tar_file.members:
39
        if member.name.endswith('/'):
40
            member.name += '/'
41
    import_archive(tree, tar_file)
42
43
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
44
class DirFileWriter(object):
45
46
    def __init__(self, fileobj, mode):
488 by Aaron Bentley
Fix tests for importing directories
47
        # We may be asked to 'append'.  If so, fileobj already has a path.
48
        # So we copy the existing tree, and overwrite afterward.
49
        fileobj.seek(0)
50
        existing = fileobj.read()
51
        fileobj.seek(0)
52
        path = tempfile.mkdtemp(dir=os.getcwd())
53
        if existing != '':
54
            # copytree requires the directory not to exist
55
            os.rmdir(path)
56
            copytree(existing, path)
57
        fileobj.write(path)
58
        self.root = path
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
59
60
    def add(self, path):
488 by Aaron Bentley
Fix tests for importing directories
61
        target_path = os.path.join(self.root, path)
62
        parent = osutils.dirname(target_path)
63
        if not os.path.exists(parent):
64
            os.makedirs(parent)
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
65
        kind = osutils.file_kind(path)
66
        if kind == 'file':
488 by Aaron Bentley
Fix tests for importing directories
67
            copy2(path, target_path)
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
68
        if kind == 'directory':
488 by Aaron Bentley
Fix tests for importing directories
69
            os.mkdir(target_path)
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
70
71
    def close(self):
72
        pass
73
74
477 by Aaron Bentley
split out upstream_import test cases
75
class TestImport(TestCaseInTempDir):
76
77
    def make_tar(self, mode='w'):
78
        def maker(fileobj):
79
            return tarfile.open('project-0.1.tar', mode, fileobj)
80
        return self.make_archive(maker)
81
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
82
    def make_archive(self, maker, subdir=True):
477 by Aaron Bentley
split out upstream_import test cases
83
        result = StringIO()
84
        archive_file = maker(result)
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
85
        try:
86
            os.mkdir('project-0.1')
87
            if subdir:
88
                prefix='project-0.1/'
89
                archive_file.add('project-0.1')
90
            else:
91
                prefix=''
92
                os.chdir('project-0.1')
93
            os.mkdir(prefix + 'junk')
94
            archive_file.add(prefix + 'junk')
531.2.2 by Charlie Shepherd
Remove all trailing whitespace
95
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
96
            f = file(prefix + 'README', 'wb')
97
            f.write('What?')
98
            f.close()
99
            archive_file.add(prefix + 'README')
100
101
            f = file(prefix + 'FEEDME', 'wb')
102
            f.write('Hungry!!')
103
            f.close()
104
            archive_file.add(prefix + 'FEEDME')
105
106
            archive_file.close()
107
        finally:
108
            if not subdir:
109
                os.chdir('..')
110
            rmtree('project-0.1')
477 by Aaron Bentley
split out upstream_import test cases
111
        result.seek(0)
112
        return result
113
491 by Aaron Bentley
Fix test suite for importing directories
114
    def make_archive2(self, builder, subdir):
477 by Aaron Bentley
split out upstream_import test cases
115
        result = StringIO()
491 by Aaron Bentley
Fix test suite for importing directories
116
        archive_file = builder(result)
477 by Aaron Bentley
split out upstream_import test cases
117
        os.mkdir('project-0.2')
491 by Aaron Bentley
Fix test suite for importing directories
118
        try:
119
            if subdir:
120
                prefix='project-0.2/'
121
                archive_file.add('project-0.2')
122
            else:
123
                prefix=''
124
                os.chdir('project-0.2')
531.2.2 by Charlie Shepherd
Remove all trailing whitespace
125
491 by Aaron Bentley
Fix test suite for importing directories
126
            os.mkdir(prefix + 'junk')
127
            archive_file.add(prefix + 'junk')
128
129
            f = file(prefix + 'README', 'wb')
130
            f.write('Now?')
131
            f.close()
132
            archive_file.add(prefix + 'README')
133
749.1.2 by Aaron Bentley
Fix Python2.7 compatibility, clarify test.
134
            f = file(prefix + 'README', 'wb')
135
            f.write('Wow?')
136
            f.close()
137
            # Add a second entry for README with different contents.
491 by Aaron Bentley
Fix test suite for importing directories
138
            archive_file.add(prefix + 'README')
139
            archive_file.close()
140
141
        finally:
142
            if not subdir:
143
                os.chdir('..')
488 by Aaron Bentley
Fix tests for importing directories
144
        result.seek(0)
477 by Aaron Bentley
split out upstream_import test cases
145
        return result
146
147
    def make_messed_tar(self):
148
        result = StringIO()
149
        tar_file = tarfile.open('project-0.1.tar', 'w', result)
150
        os.mkdir('project-0.1')
151
        tar_file.add('project-0.1')
152
153
        os.mkdir('project-0.2')
154
        tar_file.add('project-0.2')
531.2.2 by Charlie Shepherd
Remove all trailing whitespace
155
477 by Aaron Bentley
split out upstream_import test cases
156
        f = file('project-0.1/README', 'wb')
157
        f.write('What?')
158
        f.close()
159
        tar_file.add('project-0.1/README')
160
        tar_file.close()
161
        rmtree('project-0.1')
162
        result.seek(0)
163
        return result
164
165
    def make_zip(self):
166
        def maker(fileobj):
167
            return ZipFileWrapper(fileobj, 'w')
168
        return self.make_archive(maker)
169
730.2.3 by Max Bowsher
Add a very simple test.
170
    def make_tar_with_bzrdir(self):
171
        result = StringIO()
172
        tar_file = tarfile.open('tar-with-bzrdir.tar', 'w', result)
173
        os.mkdir('toplevel-dir')
174
        tar_file.add('toplevel-dir')
175
        os.mkdir('toplevel-dir/.bzr')
176
        tar_file.add('toplevel-dir/.bzr')
177
        tar_file.close()
178
        rmtree('toplevel-dir')
179
        result.seek(0)
180
        return result
181
703 by Aaron Bentley
Fix import with Python 2.6
182
    def test_top_path(self):
183
        self.assertEqual(top_path('ab/b/c'), 'ab')
184
        self.assertEqual(top_path('etc'), 'etc')
185
        self.assertEqual(top_path('project-0.1'), 'project-0.1')
477 by Aaron Bentley
split out upstream_import test cases
186
187
    def test_common_directory(self):
188
        self.assertEqual(common_directory(['ab/c/d', 'ab/c/e']), 'ab')
189
        self.assertIs(common_directory(['ab/c/d', 'ac/c/e']), None)
703 by Aaron Bentley
Fix import with Python 2.6
190
        self.assertEqual('FEEDME', common_directory(['FEEDME']))
477 by Aaron Bentley
split out upstream_import test cases
191
192
    def test_untar(self):
478 by Aaron Bentley
More test case unification
193
        def builder(fileobj, mode='w'):
194
            return tarfile.open('project-0.1.tar', mode, fileobj)
195
        self.archive_test(builder, import_tar)
196
517.1.3 by Aaron Bentley
Handle broken python tar implementations
197
    def test_broken_tar(self):
198
        def builder(fileobj, mode='w'):
199
            return tarfile.open('project-0.1.tar', mode, fileobj)
200
        self.archive_test(builder, import_tar_broken, subdir=True)
201
478 by Aaron Bentley
More test case unification
202
    def test_unzip(self):
203
        def builder(fileobj, mode='w'):
204
            return ZipFileWrapper(fileobj, mode)
205
        self.archive_test(builder, import_zip)
206
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
207
    def test_copydir_nosub(self):
208
        def builder(fileobj, mode='w'):
209
            return DirFileWriter(fileobj, mode)
489 by Aaron Bentley
import now imports directories
210
        # It would be bogus to test with the result in a subdirectory,
211
        # because for directories, the input root is always the output root.
484 by Aaron Bentley
Get closer to importing directories using the same mechanism as files
212
        self.archive_test(builder, import_dir)
213
214
    def archive_test(self, builder, importer, subdir=False):
215
        archive_file = self.make_archive(builder, subdir)
477 by Aaron Bentley
split out upstream_import test cases
216
        tree = BzrDir.create_standalone_workingtree('tree')
515.1.2 by Aaron Bentley
Fix all test suite bugs w/ dirstate
217
        tree.lock_write()
218
        try:
219
            importer(tree, archive_file)
220
            self.assertTrue(tree.path2id('README') is not None)
221
            self.assertTrue(tree.path2id('FEEDME') is not None)
222
            self.assertTrue(os.path.isfile(tree.abspath('README')))
223
            self.assertEqual(tree.inventory[tree.path2id('README')].kind,
224
                'file')
225
            self.assertEqual(tree.inventory[tree.path2id('FEEDME')].kind,
226
                'file')
227
            f = file(tree.abspath('junk/food'), 'wb')
228
            f.write('I like food\n')
229
            f.close()
477 by Aaron Bentley
split out upstream_import test cases
230
515.1.2 by Aaron Bentley
Fix all test suite bugs w/ dirstate
231
            archive_file = self.make_archive2(builder, subdir)
232
            importer(tree, archive_file)
233
            self.assertTrue(tree.path2id('README') is not None)
749.1.2 by Aaron Bentley
Fix Python2.7 compatibility, clarify test.
234
            # Ensure the second version of the file is used.
235
            self.assertEqual(tree.get_file_text(tree.path2id('README')),
236
                             'Wow?')
515.1.2 by Aaron Bentley
Fix all test suite bugs w/ dirstate
237
            self.assertTrue(not os.path.exists(tree.abspath('FEEDME')))
238
        finally:
239
            tree.unlock()
477 by Aaron Bentley
split out upstream_import test cases
240
241
242
    def test_untar2(self):
243
        tar_file = self.make_messed_tar()
244
        tree = BzrDir.create_standalone_workingtree('tree')
245
        import_tar(tree, tar_file)
531.2.2 by Charlie Shepherd
Remove all trailing whitespace
246
        self.assertTrue(tree.path2id('project-0.1/README') is not None)
477 by Aaron Bentley
split out upstream_import test cases
247
248
    def test_untar_gzip(self):
249
        tar_file = self.make_tar(mode='w:gz')
250
        tree = BzrDir.create_standalone_workingtree('tree')
251
        import_tar(tree, tar_file)
531.2.2 by Charlie Shepherd
Remove all trailing whitespace
252
        self.assertTrue(tree.path2id('README') is not None)
477 by Aaron Bentley
split out upstream_import test cases
253
730.2.3 by Max Bowsher
Add a very simple test.
254
    def test_no_crash_with_bzrdir(self):
255
        tar_file = self.make_tar_with_bzrdir()
256
        tree = BzrDir.create_standalone_workingtree('tree')
257
        import_tar(tree, tar_file)
258
        # So long as it did not crash, that should be ok
259
772 by Aaron Bentley
Better handling of compound tar names.
260
    def test_get_archive_type(self):
261
        self.assertEqual(('tar', None), get_archive_type('foo.tar'))
262
        self.assertEqual(('zip', None), get_archive_type('foo.zip'))
263
        self.assertRaises(errors.NotArchiveType, get_archive_type, 'foo.gif')
264
        self.assertEqual(('tar', 'gz'), get_archive_type('foo.tar.gz'))
265
        self.assertRaises(errors.NotArchiveType, get_archive_type,
266
                          'foo.zip.gz')
267
        self.assertEqual(('tar', 'gz'), get_archive_type('foo.tgz'))
268
        self.assertEqual(('tar', 'lzma'), get_archive_type('foo.tar.lzma'))
269
        self.assertEqual(('tar', 'lzma'), get_archive_type('foo.tar.xz'))
270
        self.assertEqual(('tar', 'bz2'), get_archive_type('foo.tar.bz2'))
271
768 by Aaron Bentley
Fix non-ascii tarball handling
272
273
class TestWithStuff(TestCaseWithTransport):
274
275
    def transform_to_tar(self, tt):
276
        stream = StringIO()
277
        tarball = tarfile.open(None, 'w|', stream)
278
        export_tarball(tt.get_preview_tree(), tarball, '')
279
        return stream
280
281
    def get_empty_tt(self):
282
        b = self.make_repository('foo')
283
        null_tree = b.revision_tree(_mod_revision.NULL_REVISION)
284
        tt = transform.TransformPreview(null_tree)
285
        root = tt.new_directory('', transform.ROOT_PARENT, 'tree-root')
286
        tt.fixup_new_roots()
287
        self.addCleanup(tt.finalize)
288
        return tt
289
290
    def test_nonascii_paths(self):
769.1.1 by Jelmer Vernooij
Skip test_nonascii_paths on platforms that don't support unicode paths.
291
        self.requireFeature(UnicodeFilenameFeature)
768 by Aaron Bentley
Fix non-ascii tarball handling
292
        tt = self.get_empty_tt()
293
        encoded_file = tt.new_file(
294
            u'\u1234file', tt.root, 'contents', 'new-file')
295
        encoded_file = tt.new_file(
296
            'other', tt.root, 'contents', 'other-file')
297
        tarfile = self.transform_to_tar(tt)
298
        tarfile.seek(0)
299
        tree = self.make_branch_and_tree('bar')
300
        import_tar(tree, tarfile)
301
        self.assertPathExists(u'bar/\u1234file')
302
303
477 by Aaron Bentley
split out upstream_import test cases
304
def test_suite():
305
    return makeSuite(TestImport)