~bzr-pqm/bzr/bzr.dev

4988.10.3 by John Arbash Meinel
Merge bzr.dev 5007, resolve conflict, update NEWS
1
# Copyright (C) 2009, 2010 Canonical Ltd
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
16
5718.5.12 by Jelmer Vernooij
Add test for export_tarball.
17
"""Tests for bzrlib.export."""
18
19
from cStringIO import StringIO
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
20
import os
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
21
import tarfile
4996.1.1 by Robert Collins
Set the file mtime when exporting to a directory to prevent triggering make rebuilds unnecessarily.
22
import time
5718.5.14 by Jelmer Vernooij
Add test for per-file-timestamp zipfiles.
23
import zipfile
4241.9.5 by Vincent Ladeuil
Fix unicode related OSX failures.
24
25
from bzrlib import (
4576.1.1 by Alexander Belchenko
Fixed export to existing empty directory.
26
    errors,
4241.9.5 by Vincent Ladeuil
Fix unicode related OSX failures.
27
    export,
28
    tests,
29
    )
5718.5.18 by Jelmer Vernooij
Don't export to '-', but rather to ''.
30
from bzrlib.export import get_root_name
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
31
from bzrlib.export.tar_exporter import export_tarball_generator
5718.5.19 by Jelmer Vernooij
Use features.
32
from bzrlib.tests import features
4241.9.5 by Vincent Ladeuil
Fix unicode related OSX failures.
33
34
5718.5.9 by Jelmer Vernooij
Add test for export zip to stdout.
35
class TestDirExport(tests.TestCaseWithTransport):
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
36
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
37
    def test_missing_file(self):
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
38
        self.build_tree(['a/', 'a/b', 'a/c'])
39
        wt = self.make_branch_and_tree('.')
40
        wt.add(['a', 'a/b', 'a/c'])
41
        os.unlink('a/c')
4241.9.5 by Vincent Ladeuil
Fix unicode related OSX failures.
42
        export.export(wt, 'target', format="dir")
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
43
        self.assertPathExists('target/a/b')
44
        self.assertPathDoesNotExist('target/a/c')
4241.9.5 by Vincent Ladeuil
Fix unicode related OSX failures.
45
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
46
    def test_empty(self):
47
        wt = self.make_branch_and_tree('.')
48
        export.export(wt, 'target', format="dir")
49
        self.assertEquals([], os.listdir("target"))
50
51
    def test_symlink(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
52
        self.requireFeature(features.SymlinkFeature)
4562.1.1 by Jelmer Vernooij
Support exporting symlinks when exporting from a working tree.
53
        wt = self.make_branch_and_tree('.')
54
        os.symlink('source', 'link')
55
        wt.add(['link'])
56
        export.export(wt, 'target', format="dir")
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
57
        self.assertPathExists('target/link')
4576.1.1 by Alexander Belchenko
Fixed export to existing empty directory.
58
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
59
    def test_to_existing_empty_dir_success(self):
4576.1.1 by Alexander Belchenko
Fixed export to existing empty directory.
60
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
61
        wt = self.make_branch_and_tree('source')
62
        wt.add(['a', 'b', 'b/c'])
63
        wt.commit('1')
64
        self.build_tree(['target/'])
65
        export.export(wt, 'target', format="dir")
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
66
        self.assertPathExists('target/a')
67
        self.assertPathExists('target/b')
68
        self.assertPathExists('target/b/c')
4576.1.1 by Alexander Belchenko
Fixed export to existing empty directory.
69
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
70
    def test_empty_subdir(self):
71
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
72
        wt = self.make_branch_and_tree('source')
73
        wt.add(['a', 'b', 'b/c'])
74
        wt.commit('1')
75
        self.build_tree(['target/'])
76
        export.export(wt, 'target', format="dir", subdir='')
77
        self.assertPathExists('target/a')
78
        self.assertPathExists('target/b')
79
        self.assertPathExists('target/b/c')
80
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
81
    def test_to_existing_nonempty_dir_fail(self):
4576.1.1 by Alexander Belchenko
Fixed export to existing empty directory.
82
        self.build_tree(['source/', 'source/a', 'source/b/', 'source/b/c'])
83
        wt = self.make_branch_and_tree('source')
84
        wt.add(['a', 'b', 'b/c'])
85
        wt.commit('1')
86
        self.build_tree(['target/', 'target/foo'])
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
87
        self.assertRaises(errors.BzrError,
88
            export.export, wt, 'target', format="dir")
4988.10.1 by michal
- bug #511987 fixed, export of single file
89
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
90
    def test_existing_single_file(self):
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
91
        self.build_tree([
92
            'dir1/', 'dir1/dir2/', 'dir1/first', 'dir1/dir2/second'])
4988.10.1 by michal
- bug #511987 fixed, export of single file
93
        wtree = self.make_branch_and_tree('dir1')
94
        wtree.add(['dir2', 'first', 'dir2/second'])
95
        wtree.commit('1')
96
        export.export(wtree, 'target1', format='dir', subdir='first')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
97
        self.assertPathExists('target1/first')
4988.10.1 by michal
- bug #511987 fixed, export of single file
98
        export.export(wtree, 'target2', format='dir', subdir='dir2/second')
5784.1.3 by Martin Pool
Switch away from using failUnlessExists and failIfExists
99
        self.assertPathExists('target2/second')
5718.5.7 by Jelmer Vernooij
Support bzr zip exporting to stdout.
100
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
101
    def test_files_same_timestamp(self):
4996.1.1 by Robert Collins
Set the file mtime when exporting to a directory to prevent triggering make rebuilds unnecessarily.
102
        builder = self.make_branch_builder('source')
103
        builder.start_series()
104
        builder.build_snapshot(None, None, [
105
            ('add', ('', 'root-id', 'directory', '')),
106
            ('add', ('a', 'a-id', 'file', 'content\n'))])
107
        builder.build_snapshot(None, None, [
108
            ('add', ('b', 'b-id', 'file', 'content\n'))])
109
        builder.finish_series()
110
        b = builder.get_branch()
111
        b.lock_read()
112
        self.addCleanup(b.unlock)
113
        tree = b.basis_tree()
114
        orig_iter_files_bytes = tree.iter_files_bytes
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
115
4996.1.1 by Robert Collins
Set the file mtime when exporting to a directory to prevent triggering make rebuilds unnecessarily.
116
        # Make iter_files_bytes slower, so we provoke mtime skew
117
        def iter_files_bytes(to_fetch):
118
            for thing in orig_iter_files_bytes(to_fetch):
119
                yield thing
120
                time.sleep(1)
121
        tree.iter_files_bytes = iter_files_bytes
122
        export.export(tree, 'target', format='dir')
123
        t = self.get_transport('target')
124
        st_a = t.stat('a')
125
        st_b = t.stat('b')
126
        # All files must be given the same mtime.
127
        self.assertEqual(st_a.st_mtime, st_b.st_mtime)
5076.2.1 by Jelmer Vernooij
Add use_tree_timestamp argument to exporters.
128
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
129
    def test_files_per_file_timestamps(self):
5076.2.1 by Jelmer Vernooij
Add use_tree_timestamp argument to exporters.
130
        builder = self.make_branch_builder('source')
131
        builder.start_series()
5151.3.1 by Martin
Fix os.utime test failures, three on FAT filesystems and one with readonly files
132
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
133
        a_time = time.mktime((1999, 12, 12, 0, 0, 0, 0, 0, 0))
134
        b_time = time.mktime((1980, 01, 01, 0, 0, 0, 0, 0, 0))
5076.2.1 by Jelmer Vernooij
Add use_tree_timestamp argument to exporters.
135
        builder.build_snapshot(None, None, [
136
            ('add', ('', 'root-id', 'directory', '')),
137
            ('add', ('a', 'a-id', 'file', 'content\n'))],
5151.3.1 by Martin
Fix os.utime test failures, three on FAT filesystems and one with readonly files
138
            timestamp=a_time)
5076.2.1 by Jelmer Vernooij
Add use_tree_timestamp argument to exporters.
139
        builder.build_snapshot(None, None, [
140
            ('add', ('b', 'b-id', 'file', 'content\n'))],
5151.3.1 by Martin
Fix os.utime test failures, three on FAT filesystems and one with readonly files
141
            timestamp=b_time)
5076.2.1 by Jelmer Vernooij
Add use_tree_timestamp argument to exporters.
142
        builder.finish_series()
143
        b = builder.get_branch()
144
        b.lock_read()
145
        self.addCleanup(b.unlock)
146
        tree = b.basis_tree()
5076.2.3 by Jelmer Vernooij
Review comments from Rob.
147
        export.export(tree, 'target', format='dir', per_file_timestamps=True)
5076.2.1 by Jelmer Vernooij
Add use_tree_timestamp argument to exporters.
148
        t = self.get_transport('target')
5151.3.1 by Martin
Fix os.utime test failures, three on FAT filesystems and one with readonly files
149
        self.assertEqual(a_time, t.stat('a').st_mtime)
150
        self.assertEqual(b_time, t.stat('b').st_mtime)
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
151
5966.1.1 by Szilveszter Farkas
Fixed exporting subdirectories with per file timestamps.
152
    def test_subdir_files_per_timestamps(self):
153
        builder = self.make_branch_builder('source')
154
        builder.start_series()
155
        foo_time = time.mktime((1999, 12, 12, 0, 0, 0, 0, 0, 0))
156
        builder.build_snapshot(None, None, [
157
            ('add', ('', 'root-id', 'directory', '')),
158
            ('add', ('subdir', 'subdir-id', 'directory', '')),
159
            ('add', ('subdir/foo.txt', 'foo-id', 'file', 'content\n'))],
160
            timestamp=foo_time)
161
        builder.finish_series()
162
        b = builder.get_branch()
163
        b.lock_read()
164
        self.addCleanup(b.unlock)
165
        tree = b.basis_tree()
166
        export.export(tree, 'target', format='dir', subdir='subdir',
167
            per_file_timestamps=True)
168
        t = self.get_transport('target')
169
        self.assertEquals(foo_time, t.stat('foo.txt').st_mtime)
170
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
171
172
class TarExporterTests(tests.TestCaseWithTransport):
173
5718.5.11 by Jelmer Vernooij
Tests, tests, tests.
174
    def test_xz(self):
5718.5.19 by Jelmer Vernooij
Use features.
175
        self.requireFeature(features.lzma)
176
        import lzma
5718.5.11 by Jelmer Vernooij
Tests, tests, tests.
177
        wt = self.make_branch_and_tree('.')
178
        self.build_tree(['a'])
179
        wt.add(["a"])
180
        wt.commit("1")
5718.5.19 by Jelmer Vernooij
Use features.
181
        export.export(wt, 'target.tar.xz', format="txz")
5718.5.11 by Jelmer Vernooij
Tests, tests, tests.
182
        tf = tarfile.open(fileobj=lzma.LZMAFile('target.tar.xz'))
183
        self.assertEquals(["target/a"], tf.getnames())
184
5718.5.17 by Jelmer Vernooij
Support tar.lzma.
185
    def test_lzma(self):
5718.5.19 by Jelmer Vernooij
Use features.
186
        self.requireFeature(features.lzma)
187
        import lzma
5718.5.17 by Jelmer Vernooij
Support tar.lzma.
188
        wt = self.make_branch_and_tree('.')
189
        self.build_tree(['a'])
190
        wt.add(["a"])
191
        wt.commit("1")
5718.5.19 by Jelmer Vernooij
Use features.
192
        export.export(wt, 'target.tar.lzma', format="tlzma")
5718.5.17 by Jelmer Vernooij
Support tar.lzma.
193
        tf = tarfile.open(fileobj=lzma.LZMAFile('target.tar.lzma'))
194
        self.assertEquals(["target/a"], tf.getnames())
195
5718.5.11 by Jelmer Vernooij
Tests, tests, tests.
196
    def test_tgz(self):
197
        wt = self.make_branch_and_tree('.')
198
        self.build_tree(['a'])
199
        wt.add(["a"])
200
        wt.commit("1")
201
        export.export(wt, 'target.tar.gz', format="tgz")
202
        tf = tarfile.open('target.tar.gz')
203
        self.assertEquals(["target/a"], tf.getnames())
204
5718.5.15 by Jelmer Vernooij
Only write out basename of the tarfile to the gzip file.
205
    def test_tgz_ignores_dest_path(self):
206
        # The target path should not be a part of the target file.
207
        # (bug #102234)
208
        wt = self.make_branch_and_tree('.')
209
        self.build_tree(['a'])
210
        wt.add(["a"])
211
        wt.commit("1")
212
        os.mkdir("testdir1")
213
        os.mkdir("testdir2")
214
        export.export(wt, 'testdir1/target.tar.gz', format="tgz",
215
            per_file_timestamps=True)
216
        export.export(wt, 'testdir2/target.tar.gz', format="tgz",
217
            per_file_timestamps=True)
218
        file1 = open('testdir1/target.tar.gz', 'r')
219
        self.addCleanup(file1.close)
220
        file2 = open('testdir1/target.tar.gz', 'r')
221
        self.addCleanup(file2.close)
222
        content1 = file1.read()
223
        content2 = file2.read()
224
        self.assertEqualDiff(content1, content2)
225
        # the gzip module doesn't have a way to read back to the original
226
        # filename, but it's stored as-is in the tarfile.
227
        self.assertFalse("testdir1" in content1)
228
        self.assertFalse("target.tar.gz" in content1)
229
        self.assertTrue("target.tar" in content1)
230
5718.5.11 by Jelmer Vernooij
Tests, tests, tests.
231
    def test_tbz2(self):
232
        wt = self.make_branch_and_tree('.')
233
        self.build_tree(['a'])
234
        wt.add(["a"])
235
        wt.commit("1")
236
        export.export(wt, 'target.tar.bz2', format="tbz2")
237
        tf = tarfile.open('target.tar.bz2')
238
        self.assertEquals(["target/a"], tf.getnames())
239
240
    def test_xz_stdout(self):
241
        wt = self.make_branch_and_tree('.')
242
        self.assertRaises(errors.BzrError, export.export, wt, '-',
243
            format="txz")
5718.5.12 by Jelmer Vernooij
Add test for export_tarball.
244
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
245
    def test_export_tarball_generator(self):
5718.5.12 by Jelmer Vernooij
Add test for export_tarball.
246
        wt = self.make_branch_and_tree('.')
247
        self.build_tree(['a'])
248
        wt.add(["a"])
249
        wt.commit("1", timestamp=42)
250
        target = StringIO()
251
        ball = tarfile.open(None, "w|", target)
252
        wt.lock_read()
253
        try:
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
254
            for _ in export_tarball_generator(wt, ball, "bar"):
255
                pass
5718.5.12 by Jelmer Vernooij
Add test for export_tarball.
256
        finally:
257
            wt.unlock()
5967.6.3 by Martin Pool
Further shrink export code
258
        # Ball should now be closed.
259
        target.seek(0)
260
        ball2 = tarfile.open(None, "r", target)
261
        self.addCleanup(ball2.close)
262
        self.assertEquals(["bar/a"], ball2.getnames())
5718.5.14 by Jelmer Vernooij
Add test for per-file-timestamp zipfiles.
263
264
265
class ZipExporterTests(tests.TestCaseWithTransport):
266
267
    def test_per_file_timestamps(self):
268
        tree = self.make_branch_and_tree('.')
269
        self.build_tree_contents([('har', 'foo')])
270
        tree.add('har')
271
        # Earliest allowable date on FAT32 filesystems is 1980-01-01
5718.5.26 by Jelmer Vernooij
Work around zip info time zone issues.
272
        timestamp = 347151600
273
        tree.commit('setup', timestamp=timestamp)
5718.5.14 by Jelmer Vernooij
Add test for per-file-timestamp zipfiles.
274
        export.export(tree.basis_tree(), 'test.zip', format='zip',
275
            per_file_timestamps=True)
276
        zfile = zipfile.ZipFile('test.zip')
277
        info = zfile.getinfo("test/har")
5718.5.26 by Jelmer Vernooij
Work around zip info time zone issues.
278
        self.assertEquals(time.localtime(timestamp)[:6], info.date_time)
5718.5.18 by Jelmer Vernooij
Don't export to '-', but rather to ''.
279
280
281
class RootNameTests(tests.TestCase):
282
283
    def test_root_name(self):
284
        self.assertEquals('mytest', get_root_name('../mytest.tar'))
285
        self.assertEquals('mytar', get_root_name('mytar.tar'))
286
        self.assertEquals('mytar', get_root_name('mytar.tar.bz2'))
287
        self.assertEquals('tar.tar.tar', get_root_name('tar.tar.tar.tgz'))
288
        self.assertEquals('bzr-0.0.5', get_root_name('bzr-0.0.5.tar.gz'))
289
        self.assertEquals('bzr-0.0.5', get_root_name('bzr-0.0.5.zip'))
290
        self.assertEquals('bzr-0.0.5', get_root_name('bzr-0.0.5'))
291
        self.assertEquals('mytar', get_root_name('a/long/path/mytar.tgz'))
292
        self.assertEquals('other',
293
            get_root_name('../parent/../dir/other.tbz2'))
294
        self.assertEquals('', get_root_name('-'))