/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_export.py

  • Committer: Jelmer Vernooij
  • Date: 2020-04-05 19:11:34 UTC
  • mto: (7490.7.16 work)
  • mto: This revision was merged to the branch mainline in revision 7501.
  • Revision ID: jelmer@jelmer.uk-20200405191134-0aebh8ikiwygxma5
Populate the .gitignore file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2009, 2010, 2011, 2016 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
"""Tests for breezy.export."""
 
18
 
 
19
import gzip
17
20
import os
 
21
import tarfile
18
22
import time
 
23
import zipfile
19
24
 
20
 
from bzrlib import (
 
25
from .. import (
21
26
    errors,
22
27
    export,
23
28
    tests,
24
29
    )
25
 
 
26
 
 
27
 
class TestExport(tests.TestCaseWithTransport):
28
 
 
29
 
    def test_dir_export_missing_file(self):
 
30
from ..export import get_root_name
 
31
from ..archive.tar import tarball_generator
 
32
from ..sixish import (
 
33
    BytesIO,
 
34
    )
 
35
from . import features
 
36
 
 
37
 
 
38
class TestDirExport(tests.TestCaseWithTransport):
 
39
 
 
40
    def test_missing_file(self):
30
41
        self.build_tree(['a/', 'a/b', 'a/c'])
31
42
        wt = self.make_branch_and_tree('.')
32
43
        wt.add(['a', 'a/b', 'a/c'])
33
44
        os.unlink('a/c')
34
45
        export.export(wt, 'target', format="dir")
35
 
        self.failUnlessExists('target/a/b')
36
 
        self.failIfExists('target/a/c')
37
 
 
38
 
    def test_dir_export_symlink(self):
39
 
        self.requireFeature(tests.SymlinkFeature)
 
46
        self.assertPathExists('target/a/b')
 
47
        self.assertPathDoesNotExist('target/a/c')
 
48
 
 
49
    def test_empty(self):
 
50
        wt = self.make_branch_and_tree('.')
 
51
        export.export(wt, 'target', format="dir")
 
52
        self.assertEqual([], os.listdir("target"))
 
53
 
 
54
    def test_symlink(self):
 
55
        self.requireFeature(features.SymlinkFeature)
40
56
        wt = self.make_branch_and_tree('.')
41
57
        os.symlink('source', 'link')
42
58
        wt.add(['link'])
43
59
        export.export(wt, 'target', format="dir")
44
 
        self.failUnlessExists('target/link')
45
 
 
46
 
    def test_dir_export_to_existing_empty_dir_success(self):
47
 
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
48
 
        wt = self.make_branch_and_tree('source')
49
 
        wt.add(['a', 'b', 'b/c'])
50
 
        wt.commit('1')
51
 
        self.build_tree(['target/'])
52
 
        export.export(wt, 'target', format="dir")
53
 
        self.failUnlessExists('target/a')
54
 
        self.failUnlessExists('target/b')
55
 
        self.failUnlessExists('target/b/c')
56
 
 
57
 
    def test_dir_export_to_existing_nonempty_dir_fail(self):
 
60
        self.assertPathExists('target/link')
 
61
 
 
62
    def test_nested_tree(self):
 
63
        wt = self.make_branch_and_tree('.', format='development-subtree')
 
64
        subtree = self.make_branch_and_tree('subtree')
 
65
        self.build_tree(['subtree/file'])
 
66
        subtree.add(['file'])
 
67
        wt.add(['subtree'])
 
68
        export.export(wt, 'target', format="dir")
 
69
        self.assertPathExists('target/subtree')
 
70
        # TODO(jelmer): Once iter_entries_by_dir supports nested tree iteration:
 
71
        # self.assertPathExists('target/subtree/file')
 
72
 
 
73
    def test_to_existing_empty_dir_success(self):
 
74
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
 
75
        wt = self.make_branch_and_tree('source')
 
76
        wt.add(['a', 'b', 'b/c'])
 
77
        wt.commit('1')
 
78
        self.build_tree(['target/'])
 
79
        export.export(wt, 'target', format="dir")
 
80
        self.assertPathExists('target/a')
 
81
        self.assertPathExists('target/b')
 
82
        self.assertPathExists('target/b/c')
 
83
 
 
84
    def test_empty_subdir(self):
 
85
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
 
86
        wt = self.make_branch_and_tree('source')
 
87
        wt.add(['a', 'b', 'b/c'])
 
88
        wt.commit('1')
 
89
        self.build_tree(['target/'])
 
90
        export.export(wt, 'target', format="dir", subdir='')
 
91
        self.assertPathExists('target/a')
 
92
        self.assertPathExists('target/b')
 
93
        self.assertPathExists('target/b/c')
 
94
 
 
95
    def test_to_existing_nonempty_dir_fail(self):
58
96
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
59
97
        wt = self.make_branch_and_tree('source')
60
98
        wt.add(['a', 'b', 'b/c'])
61
99
        wt.commit('1')
62
100
        self.build_tree(['target/', 'target/foo'])
63
 
        self.assertRaises(errors.BzrError, export.export, wt, 'target', format="dir")
 
101
        self.assertRaises(errors.BzrError,
 
102
                          export.export, wt, 'target', format="dir")
64
103
 
65
 
    def test_dir_export_existing_single_file(self):
66
 
        self.build_tree(['dir1/', 'dir1/dir2/', 'dir1/first', 'dir1/dir2/second'])
 
104
    def test_existing_single_file(self):
 
105
        self.build_tree([
 
106
            'dir1/', 'dir1/dir2/', 'dir1/first', 'dir1/dir2/second'])
67
107
        wtree = self.make_branch_and_tree('dir1')
68
108
        wtree.add(['dir2', 'first', 'dir2/second'])
69
109
        wtree.commit('1')
70
110
        export.export(wtree, 'target1', format='dir', subdir='first')
71
 
        self.failUnlessExists('target1/first')
 
111
        self.assertPathExists('target1/first')
72
112
        export.export(wtree, 'target2', format='dir', subdir='dir2/second')
73
 
        self.failUnlessExists('target2/second')
74
 
        
75
 
    def test_dir_export_files_same_timestamp(self):
 
113
        self.assertPathExists('target2/second')
 
114
 
 
115
    def test_files_same_timestamp(self):
76
116
        builder = self.make_branch_builder('source')
77
117
        builder.start_series()
78
 
        builder.build_snapshot(None, None, [
79
 
            ('add', ('', 'root-id', 'directory', '')),
80
 
            ('add', ('a', 'a-id', 'file', 'content\n'))])
81
 
        builder.build_snapshot(None, None, [
82
 
            ('add', ('b', 'b-id', 'file', 'content\n'))])
 
118
        builder.build_snapshot(None, [
 
119
            ('add', ('', b'root-id', 'directory', '')),
 
120
            ('add', ('a', b'a-id', 'file', b'content\n'))])
 
121
        builder.build_snapshot(None, [
 
122
            ('add', ('b', b'b-id', 'file', b'content\n'))])
83
123
        builder.finish_series()
84
124
        b = builder.get_branch()
85
125
        b.lock_read()
86
126
        self.addCleanup(b.unlock)
87
127
        tree = b.basis_tree()
88
128
        orig_iter_files_bytes = tree.iter_files_bytes
 
129
 
89
130
        # Make iter_files_bytes slower, so we provoke mtime skew
90
131
        def iter_files_bytes(to_fetch):
91
132
            for thing in orig_iter_files_bytes(to_fetch):
99
140
        # All files must be given the same mtime.
100
141
        self.assertEqual(st_a.st_mtime, st_b.st_mtime)
101
142
 
102
 
    def test_dir_export_files_per_file_timestamps(self):
 
143
    def test_files_per_file_timestamps(self):
103
144
        builder = self.make_branch_builder('source')
104
145
        builder.start_series()
105
146
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
106
147
        a_time = time.mktime((1999, 12, 12, 0, 0, 0, 0, 0, 0))
107
 
        b_time = time.mktime((1980, 01, 01, 0, 0, 0, 0, 0, 0))
108
 
        builder.build_snapshot(None, None, [
109
 
            ('add', ('', 'root-id', 'directory', '')),
110
 
            ('add', ('a', 'a-id', 'file', 'content\n'))],
 
148
        b_time = time.mktime((1980, 0o1, 0o1, 0, 0, 0, 0, 0, 0))
 
149
        builder.build_snapshot(None, [
 
150
            ('add', ('', b'root-id', 'directory', '')),
 
151
            ('add', ('a', b'a-id', 'file', b'content\n'))],
111
152
            timestamp=a_time)
112
 
        builder.build_snapshot(None, None, [
113
 
            ('add', ('b', 'b-id', 'file', 'content\n'))],
 
153
        builder.build_snapshot(None, [
 
154
            ('add', ('b', b'b-id', 'file', b'content\n'))],
114
155
            timestamp=b_time)
115
156
        builder.finish_series()
116
157
        b = builder.get_branch()
121
162
        t = self.get_transport('target')
122
163
        self.assertEqual(a_time, t.stat('a').st_mtime)
123
164
        self.assertEqual(b_time, t.stat('b').st_mtime)
 
165
 
 
166
    def test_subdir_files_per_timestamps(self):
 
167
        builder = self.make_branch_builder('source')
 
168
        builder.start_series()
 
169
        foo_time = time.mktime((1999, 12, 12, 0, 0, 0, 0, 0, 0))
 
170
        builder.build_snapshot(None, [
 
171
            ('add', ('', b'root-id', 'directory', '')),
 
172
            ('add', ('subdir', b'subdir-id', 'directory', '')),
 
173
            ('add', ('subdir/foo.txt', b'foo-id', 'file', b'content\n'))],
 
174
            timestamp=foo_time)
 
175
        builder.finish_series()
 
176
        b = builder.get_branch()
 
177
        b.lock_read()
 
178
        self.addCleanup(b.unlock)
 
179
        tree = b.basis_tree()
 
180
        export.export(tree, 'target', format='dir', subdir='subdir',
 
181
                      per_file_timestamps=True)
 
182
        t = self.get_transport('target')
 
183
        self.assertEqual(foo_time, t.stat('foo.txt').st_mtime)
 
184
 
 
185
 
 
186
class TarExporterTests(tests.TestCaseWithTransport):
 
187
 
 
188
    def test_xz(self):
 
189
        self.requireFeature(features.lzma)
 
190
        import lzma
 
191
        wt = self.make_branch_and_tree('.')
 
192
        self.build_tree(['a'])
 
193
        wt.add(["a"])
 
194
        wt.commit("1")
 
195
        export.export(wt, 'target.tar.xz', format="txz")
 
196
        tf = tarfile.open(fileobj=lzma.LZMAFile('target.tar.xz'))
 
197
        self.assertEqual(["target/a"], tf.getnames())
 
198
 
 
199
    def test_lzma(self):
 
200
        self.requireFeature(features.lzma)
 
201
        import lzma
 
202
        wt = self.make_branch_and_tree('.')
 
203
        self.build_tree(['a'])
 
204
        wt.add(["a"])
 
205
        wt.commit("1")
 
206
        export.export(wt, 'target.tar.lzma', format="tlzma")
 
207
        tf = tarfile.open(fileobj=lzma.LZMAFile('target.tar.lzma'))
 
208
        self.assertEqual(["target/a"], tf.getnames())
 
209
 
 
210
    def test_tgz(self):
 
211
        wt = self.make_branch_and_tree('.')
 
212
        self.build_tree(['a'])
 
213
        wt.add(["a"])
 
214
        wt.commit("1")
 
215
        export.export(wt, 'target.tar.gz', format="tgz")
 
216
        tf = tarfile.open('target.tar.gz')
 
217
        self.assertEqual(["target/a"], tf.getnames())
 
218
 
 
219
    def test_tgz_consistent_mtime(self):
 
220
        wt = self.make_branch_and_tree('.')
 
221
        self.build_tree(['a'])
 
222
        wt.add(["a"])
 
223
        timestamp = 1547400500
 
224
        revid = wt.commit("1", timestamp=timestamp)
 
225
        revtree = wt.branch.repository.revision_tree(revid)
 
226
        export.export(revtree, 'target.tar.gz', format="tgz")
 
227
        with gzip.GzipFile('target.tar.gz', 'r') as f:
 
228
            f.read()
 
229
            self.assertEqual(int(f.mtime), timestamp)
 
230
 
 
231
    def test_tgz_ignores_dest_path(self):
 
232
        # The target path should not be a part of the target file.
 
233
        # (bug #102234)
 
234
        wt = self.make_branch_and_tree('.')
 
235
        self.build_tree(['a'])
 
236
        wt.add(["a"])
 
237
        wt.commit("1")
 
238
        os.mkdir("testdir1")
 
239
        os.mkdir("testdir2")
 
240
        export.export(wt, 'testdir1/target.tar.gz', format="tgz",
 
241
                      per_file_timestamps=True)
 
242
        export.export(wt, 'testdir2/target.tar.gz', format="tgz",
 
243
                      per_file_timestamps=True)
 
244
        file1 = open('testdir1/target.tar.gz', 'rb')
 
245
        self.addCleanup(file1.close)
 
246
        file2 = open('testdir1/target.tar.gz', 'rb')
 
247
        self.addCleanup(file2.close)
 
248
        content1 = file1.read()
 
249
        content2 = file2.read()
 
250
        self.assertEqualDiff(content1, content2)
 
251
        # the gzip module doesn't have a way to read back to the original
 
252
        # filename, but it's stored as-is in the tarfile.
 
253
        self.assertFalse(b"testdir1" in content1)
 
254
        self.assertFalse(b"target.tar.gz" in content1)
 
255
        self.assertTrue(b"target.tar" in content1)
 
256
 
 
257
    def test_tbz2(self):
 
258
        wt = self.make_branch_and_tree('.')
 
259
        self.build_tree(['a'])
 
260
        wt.add(["a"])
 
261
        wt.commit("1")
 
262
        export.export(wt, 'target.tar.bz2', format="tbz2")
 
263
        tf = tarfile.open('target.tar.bz2')
 
264
        self.assertEqual(["target/a"], tf.getnames())
 
265
 
 
266
    def test_export_tarball_generator(self):
 
267
        wt = self.make_branch_and_tree('.')
 
268
        self.build_tree(['a'])
 
269
        wt.add(["a"])
 
270
        wt.commit("1", timestamp=42)
 
271
        target = BytesIO()
 
272
        with wt.lock_read():
 
273
            target.writelines(tarball_generator(wt, "bar"))
 
274
        # Ball should now be closed.
 
275
        target.seek(0)
 
276
        ball2 = tarfile.open(None, "r", target)
 
277
        self.addCleanup(ball2.close)
 
278
        self.assertEqual(["bar/a"], ball2.getnames())
 
279
 
 
280
 
 
281
class ZipExporterTests(tests.TestCaseWithTransport):
 
282
 
 
283
    def test_per_file_timestamps(self):
 
284
        tree = self.make_branch_and_tree('.')
 
285
        self.build_tree_contents([('har', b'foo')])
 
286
        tree.add('har')
 
287
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
 
288
        timestamp = 347151600
 
289
        tree.commit('setup', timestamp=timestamp)
 
290
        export.export(tree.basis_tree(), 'test.zip', format='zip',
 
291
                      per_file_timestamps=True)
 
292
        zfile = zipfile.ZipFile('test.zip')
 
293
        info = zfile.getinfo("test/har")
 
294
        self.assertEqual(time.localtime(timestamp)[:6], info.date_time)
 
295
 
 
296
 
 
297
class RootNameTests(tests.TestCase):
 
298
 
 
299
    def test_root_name(self):
 
300
        self.assertEqual('mytest', get_root_name('../mytest.tar'))
 
301
        self.assertEqual('mytar', get_root_name('mytar.tar'))
 
302
        self.assertEqual('mytar', get_root_name('mytar.tar.bz2'))
 
303
        self.assertEqual('tar.tar.tar', get_root_name('tar.tar.tar.tgz'))
 
304
        self.assertEqual('bzr-0.0.5', get_root_name('bzr-0.0.5.tar.gz'))
 
305
        self.assertEqual('bzr-0.0.5', get_root_name('bzr-0.0.5.zip'))
 
306
        self.assertEqual('bzr-0.0.5', get_root_name('bzr-0.0.5'))
 
307
        self.assertEqual('mytar', get_root_name('a/long/path/mytar.tgz'))
 
308
        self.assertEqual('other',
 
309
                         get_root_name('../parent/../dir/other.tbz2'))
 
310
        self.assertEqual('', get_root_name('-'))