/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6637.1.2 by Jelmer Vernooij
Add tests.
1
# Copyright (C) 2006-2012 Aaron Bentley
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
import os
18
from StringIO import StringIO
19
from shutil import rmtree, copy2, copytree
20
import tarfile
21
import tempfile
6637.1.5 by Jelmer Vernooij
Ignore warning.
22
import warnings
6637.1.2 by Jelmer Vernooij
Add tests.
23
24
from .. import (
25
    osutils,
26
    revision as _mod_revision,
27
    transform
28
    )
29
from ..bzrdir import BzrDir
30
from ..export import export
31
from ..upstream_import import (
32
    common_directory,
33
    get_archive_type,
34
    import_archive,
35
    import_tar,
36
    import_zip,
37
    import_dir,
38
    NotArchiveType,
39
    top_path,
40
    ZipFileWrapper,
41
)
42
from . import (
43
    TestCaseInTempDir,
44
    TestCaseWithTransport,
45
    )
46
from .features import UnicodeFilenameFeature
47
48
49
def import_tar_broken(tree, tar_input):
50
    """
51
    Import a tarfile with names that that end in //, e.g. Feisty Python 2.5
52
    """
53
    tar_file = tarfile.open('lala', 'r', tar_input)
54
    for member in tar_file.members:
55
        if member.name.endswith('/'):
56
            member.name += '/'
57
    import_archive(tree, tar_file)
58
59
60
class DirFileWriter(object):
61
62
    def __init__(self, fileobj, mode):
63
        # We may be asked to 'append'.  If so, fileobj already has a path.
64
        # So we copy the existing tree, and overwrite afterward.
65
        fileobj.seek(0)
66
        existing = fileobj.read()
67
        fileobj.seek(0)
68
        path = tempfile.mkdtemp(dir=os.getcwd())
69
        if existing != '':
70
            # copytree requires the directory not to exist
71
            os.rmdir(path)
72
            copytree(existing, path)
73
        fileobj.write(path)
74
        self.root = path
75
76
    def add(self, path):
77
        target_path = os.path.join(self.root, path)
78
        parent = osutils.dirname(target_path)
79
        if not os.path.exists(parent):
80
            os.makedirs(parent)
81
        kind = osutils.file_kind(path)
82
        if kind == 'file':
83
            copy2(path, target_path)
84
        if kind == 'directory':
85
            os.mkdir(target_path)
86
87
    def close(self):
88
        pass
89
90
91
class TestImport(TestCaseInTempDir):
92
93
    def make_tar(self, mode='w'):
94
        def maker(fileobj):
95
            return tarfile.open('project-0.1.tar', mode, fileobj)
96
        return self.make_archive(maker)
97
98
    def make_archive(self, maker, subdir=True):
99
        result = StringIO()
100
        archive_file = maker(result)
101
        try:
102
            os.mkdir('project-0.1')
103
            if subdir:
104
                prefix='project-0.1/'
105
                archive_file.add('project-0.1')
106
            else:
107
                prefix=''
108
                os.chdir('project-0.1')
109
            os.mkdir(prefix + 'junk')
110
            archive_file.add(prefix + 'junk')
111
112
            f = file(prefix + 'README', 'wb')
113
            f.write('What?')
114
            f.close()
115
            archive_file.add(prefix + 'README')
116
117
            f = file(prefix + 'FEEDME', 'wb')
118
            f.write('Hungry!!')
119
            f.close()
120
            archive_file.add(prefix + 'FEEDME')
121
122
            archive_file.close()
123
        finally:
124
            if not subdir:
125
                os.chdir('..')
126
            rmtree('project-0.1')
127
        result.seek(0)
128
        return result
129
130
    def make_archive2(self, builder, subdir):
131
        result = StringIO()
132
        archive_file = builder(result)
133
        os.mkdir('project-0.2')
134
        try:
135
            if subdir:
136
                prefix='project-0.2/'
137
                archive_file.add('project-0.2')
138
            else:
139
                prefix=''
140
                os.chdir('project-0.2')
141
142
            os.mkdir(prefix + 'junk')
143
            archive_file.add(prefix + 'junk')
144
145
            f = file(prefix + 'README', 'wb')
146
            f.write('Now?')
147
            f.close()
148
            archive_file.add(prefix + 'README')
149
150
            f = file(prefix + 'README', 'wb')
151
            f.write('Wow?')
152
            f.close()
153
            # Add a second entry for README with different contents.
154
            archive_file.add(prefix + 'README')
155
            archive_file.close()
156
157
        finally:
158
            if not subdir:
159
                os.chdir('..')
160
        result.seek(0)
161
        return result
162
163
    def make_messed_tar(self):
164
        result = StringIO()
165
        tar_file = tarfile.open('project-0.1.tar', 'w', result)
166
        os.mkdir('project-0.1')
167
        tar_file.add('project-0.1')
168
169
        os.mkdir('project-0.2')
170
        tar_file.add('project-0.2')
171
172
        f = file('project-0.1/README', 'wb')
173
        f.write('What?')
174
        f.close()
175
        tar_file.add('project-0.1/README')
176
        tar_file.close()
177
        rmtree('project-0.1')
178
        result.seek(0)
179
        return result
180
181
    def make_zip(self):
182
        def maker(fileobj):
183
            return ZipFileWrapper(fileobj, 'w')
184
        return self.make_archive(maker)
185
186
    def make_tar_with_bzrdir(self):
187
        result = StringIO()
188
        tar_file = tarfile.open('tar-with-bzrdir.tar', 'w', result)
189
        os.mkdir('toplevel-dir')
190
        tar_file.add('toplevel-dir')
191
        os.mkdir('toplevel-dir/.bzr')
192
        tar_file.add('toplevel-dir/.bzr')
193
        tar_file.close()
194
        rmtree('toplevel-dir')
195
        result.seek(0)
196
        return result
197
198
    def test_top_path(self):
199
        self.assertEqual(top_path('ab/b/c'), 'ab')
200
        self.assertEqual(top_path('etc'), 'etc')
201
        self.assertEqual(top_path('project-0.1'), 'project-0.1')
202
203
    def test_common_directory(self):
204
        self.assertEqual(common_directory(['ab/c/d', 'ab/c/e']), 'ab')
205
        self.assertIs(common_directory(['ab/c/d', 'ac/c/e']), None)
206
        self.assertEqual('FEEDME', common_directory(['FEEDME']))
207
208
    def test_untar(self):
209
        def builder(fileobj, mode='w'):
210
            return tarfile.open('project-0.1.tar', mode, fileobj)
211
        self.archive_test(builder, import_tar)
212
213
    def test_broken_tar(self):
214
        def builder(fileobj, mode='w'):
215
            return tarfile.open('project-0.1.tar', mode, fileobj)
216
        self.archive_test(builder, import_tar_broken, subdir=True)
217
218
    def test_unzip(self):
219
        def builder(fileobj, mode='w'):
220
            return ZipFileWrapper(fileobj, mode)
221
        self.archive_test(builder, import_zip)
222
223
    def test_copydir_nosub(self):
224
        def builder(fileobj, mode='w'):
225
            return DirFileWriter(fileobj, mode)
226
        # It would be bogus to test with the result in a subdirectory,
227
        # because for directories, the input root is always the output root.
228
        self.archive_test(builder, import_dir)
229
230
    def archive_test(self, builder, importer, subdir=False):
231
        archive_file = self.make_archive(builder, subdir)
232
        tree = BzrDir.create_standalone_workingtree('tree')
233
        tree.lock_write()
234
        try:
235
            importer(tree, archive_file)
236
            self.assertTrue(tree.path2id('README') is not None)
237
            self.assertTrue(tree.path2id('FEEDME') is not None)
238
            self.assertTrue(os.path.isfile(tree.abspath('README')))
239
            self.assertEqual(tree.stored_kind(tree.path2id('README')),
240
                'file')
241
            self.assertEqual(tree.stored_kind(tree.path2id('FEEDME')),
242
                'file')
243
            f = file(tree.abspath('junk/food'), 'wb')
244
            f.write('I like food\n')
245
            f.close()
246
6637.1.5 by Jelmer Vernooij
Ignore warning.
247
            with warnings.catch_warnings():
248
                warnings.simplefilter('ignore')
249
                archive_file = self.make_archive2(builder, subdir)
250
                importer(tree, archive_file)
6637.1.2 by Jelmer Vernooij
Add tests.
251
            self.assertTrue(tree.path2id('README') is not None)
252
            # Ensure the second version of the file is used.
253
            self.assertEqual(tree.get_file_text(tree.path2id('README')),
254
                             'Wow?')
255
            self.assertTrue(not os.path.exists(tree.abspath('FEEDME')))
256
        finally:
257
            tree.unlock()
258
259
260
    def test_untar2(self):
261
        tar_file = self.make_messed_tar()
262
        tree = BzrDir.create_standalone_workingtree('tree')
263
        import_tar(tree, tar_file)
264
        self.assertTrue(tree.path2id('project-0.1/README') is not None)
265
266
    def test_untar_gzip(self):
267
        tar_file = self.make_tar(mode='w:gz')
268
        tree = BzrDir.create_standalone_workingtree('tree')
269
        import_tar(tree, tar_file)
270
        self.assertTrue(tree.path2id('README') is not None)
271
272
    def test_no_crash_with_bzrdir(self):
273
        tar_file = self.make_tar_with_bzrdir()
274
        tree = BzrDir.create_standalone_workingtree('tree')
275
        import_tar(tree, tar_file)
276
        # So long as it did not crash, that should be ok
277
278
    def test_get_archive_type(self):
279
        self.assertEqual(('tar', None), get_archive_type('foo.tar'))
280
        self.assertEqual(('zip', None), get_archive_type('foo.zip'))
281
        self.assertRaises(NotArchiveType, get_archive_type, 'foo.gif')
282
        self.assertEqual(('tar', 'gz'), get_archive_type('foo.tar.gz'))
283
        self.assertRaises(NotArchiveType, get_archive_type,
284
                          'foo.zip.gz')
285
        self.assertEqual(('tar', 'gz'), get_archive_type('foo.tgz'))
286
        self.assertEqual(('tar', 'lzma'), get_archive_type('foo.tar.lzma'))
287
        self.assertEqual(('tar', 'lzma'), get_archive_type('foo.tar.xz'))
288
        self.assertEqual(('tar', 'bz2'), get_archive_type('foo.tar.bz2'))
289
290
291
class TestWithStuff(TestCaseWithTransport):
292
293
    def transform_to_tar(self, tt):
294
        stream = StringIO()
295
        export(tt.get_preview_tree(), root='', fileobj=stream, format='tar',
296
               dest=None)
297
        return stream
298
299
    def get_empty_tt(self):
300
        b = self.make_repository('foo')
301
        null_tree = b.revision_tree(_mod_revision.NULL_REVISION)
302
        tt = transform.TransformPreview(null_tree)
303
        root = tt.new_directory('', transform.ROOT_PARENT, 'tree-root')
304
        tt.fixup_new_roots()
305
        self.addCleanup(tt.finalize)
306
        return tt
307
308
    def test_nonascii_paths(self):
309
        self.requireFeature(UnicodeFilenameFeature)
310
        tt = self.get_empty_tt()
311
        encoded_file = tt.new_file(
312
            u'\u1234file', tt.root, 'contents', 'new-file')
313
        encoded_file = tt.new_file(
314
            'other', tt.root, 'contents', 'other-file')
315
        tarfile = self.transform_to_tar(tt)
316
        tarfile.seek(0)
317
        tree = self.make_branch_and_tree('bar')
318
        import_tar(tree, tarfile)
319
        self.assertPathExists(u'bar/\u1234file')