36
38
class TestExport(TestCaseWithTransport):
38
def test_tar_export(self):
39
tree = self.make_branch_and_tree('tar')
40
self.build_tree(['tar/a'])
40
# On Windows, if we fail to set the binary bit, and a '\r' or '\n'
41
# ends up in the data stream, we will get corruption. Add a fair amount
42
# of random data, to help ensure there is at least one.
43
_file_content = ('!\r\n\t\n \r'
44
+ 'r29trp9i1r8k0e24c2o7mcx2isrlaw7toh1hv2mtst3o1udkl36v9xn2z8kt\n'
45
'tvjn7e3i9cj1qs1rw9gcye9w72cbdueiufw8nky7bs08lwggir59d62knecp\n'
46
'7s0537r8sg3e8hdnidji49rswo47c3j8190nh8emef2b6j1mf5kdq45nt3f5\n'
47
'1sz9u7fuzrm4w8bebre7p62sh5os2nkj2iiyuk9n0w0pjpdulu9k2aajejah\n'
48
'ini90ny40qzs12ajuy0ua6l178n93lvy2atqngnntsmtlmqx7yhp0q9a1xr4\n'
49
'1n69kgbo6qu9osjpqq83446r00jijtcstzybfqwm1lnt9spnri2j07bt7bbh\n'
50
'rf3ejatdxta83te2s0pt9rc4hidgy3d2pc53p4wscdt2b1dfxdj9utf5m17f\n'
51
'f03oofcau950o090vyx6m72vfkywo7gp3ajzi6uk02dwqwtumq4r44xx6ho7\n'
52
'nhynborjdjep5j53f9548msb7gd3x9a1xveb4s8zfo6cbdw2kdngcrbakwu8\n'
53
'ql5a8l94gplkwr7oypw5nt1gj5i3xwadyjfr3lb61tfkz31ba7uda9knb294\n'
54
'1azhfta0q3ry9x36lxyanvhp0g5z0t5a0i4wnoc8p4htexi915y1cnw4nznn\n'
55
'aj70dvp88ifiblv2bsp98hz570teinj8g472ddxni9ydmazfzwtznbf3hrg6\n'
56
'84gigirjt6n2yagf70036m8d73cz0jpcighpjtxsmbgzbxx7nb4ewq6jbgnc\n'
57
'hux1b0qtsdi0zfhj6g1otf5jcldmtdvuon8y1ttszkqw3ograwi25yl921hy\n'
58
'izgscmfha9xdhxxabs07b40secpw22ah9iwpbmsns6qz0yr6fswto3ft2ez5\n'
59
'ngn48pdfxj1pw246drmj1y2ll5af5w7cz849rapzd9ih7qvalw358co0yzrs\n'
60
'xan9291d1ivjku4o5gjrsnmllrqwxwy86pcivinbmlnzasa9v3o22lgv4uyd\n'
61
'q8kw77bge3hr5rr5kzwjxk223bkmo3z9oju0954undsz8axr3kb3730otrcr\n'
62
'9cwhu37htnizdwxmpoc5qmobycfm7ubbykfumv6zgkl6b8zlslwl7a8b81vz\n'
63
'3weqkvv5csfza9xvwypr6lo0t03fwp0ihmci3m1muh0lf2u30ze0hjag691j\n'
64
'27fjtd3e3zbiin5n2hq21iuo09ukbs73r5rt7vaw6axvoilvdciir9ugjh2c\n'
65
'na2b8dr0ptftoyhyxv1iwg661y338e28fhz4xxwgv3hnoe98ydfa1oou45vj\n'
66
'ln74oac2keqt0agbylrqhfscin7ireae2bql7z2le823ksy47ud57z8ctomp\n'
67
'31s1vwbczdjwqp0o2jc7mkrurvzg8mj2zwcn2iily4gcl4sy4fsh4rignlyz\n')
69
def make_basic_tree(self):
70
tree = self.make_branch_and_tree('tree')
71
self.build_tree_contents([('tree/a', self._file_content)])
42
self.build_tree_contents([('tar/.bzrrules', '')])
44
self.build_tree(['tar/.bzr-adir/', 'tar/.bzr-adir/afile'])
45
tree.add(['.bzr-adir/', '.bzr-adir/afile'])
48
self.run_bzr('ignore something')
76
def make_tree_with_extra_bzr_files(self):
77
tree = self.make_basic_tree()
78
self.build_tree_contents([('tree/.bzrrules', '')])
79
self.build_tree(['tree/.bzr-adir/', 'tree/.bzr-adir/afile'])
80
tree.add(['.bzrrules', '.bzr-adir/', '.bzr-adir/afile'])
82
self.run_bzr('ignore something -d tree')
86
def test_tar_export_ignores_bzr(self):
87
tree = self.make_tree_with_extra_bzr_files()
51
89
self.failUnless(tree.has_filename('.bzrignore'))
52
90
self.failUnless(tree.has_filename('.bzrrules'))
53
91
self.failUnless(tree.has_filename('.bzr-adir'))
54
92
self.failUnless(tree.has_filename('.bzr-adir/afile'))
55
self.run_bzr('export test.tar.gz')
93
self.run_bzr('export test.tar.gz -d tree')
56
94
ball = tarfile.open('test.tar.gz')
57
95
# Make sure the tarball contains 'a', but does not contain
59
self.assertEqual(['test/a'], sorted(ball.getnames()))
61
if sys.version_info < (2, 5, 2) and sys.platform == 'darwin':
62
raise tests.KnownFailure('python %r has a tar related bug, upgrade'
63
% (sys.version_info,))
64
out, err = self.run_bzr('export --format=tgz --root=test -')
65
ball = tarfile.open('', fileobj=StringIO(out))
66
self.assertEqual(['test/a'], sorted(ball.getnames()))
68
def test_tar_export_unicode(self):
97
self.assertEqual(['test/a'],
98
sorted(ball.getnames()))
100
def test_tar_export_unicode_filename(self):
101
self.requireFeature(tests.UnicodeFilenameFeature)
69
102
tree = self.make_branch_and_tree('tar')
70
103
# FIXME: using fname = u'\xe5.txt' below triggers a bug revealed since
71
104
# bzr.dev revno 4216 but more related to OSX/working trees/unicode than
72
105
# export itself --vila 20090406
73
106
fname = u'\N{Euro Sign}.txt'
75
self.build_tree(['tar/' + fname])
77
raise tests.TestSkipped('Unable to represent path %r' % (fname,))
107
self.build_tree(['tar/' + fname])
79
109
tree.commit('first')
82
self.run_bzr('export test.tar')
111
self.run_bzr('export test.tar -d tar')
83
112
ball = tarfile.open('test.tar')
84
113
# all paths are prefixed with the base name of the tarball
85
114
self.assertEqual(['test/' + fname.encode('utf8')],
88
117
def test_tar_export_unicode_basedir(self):
89
118
"""Test for bug #413406"""
119
self.requireFeature(tests.UnicodeFilenameFeature)
90
120
basedir = u'\N{euro sign}'
93
self.run_bzr(['init', 'branch'])
95
self.run_bzr(['export', '--format', 'tgz', u'test.tar.gz'])
97
def test_zip_export(self):
98
tree = self.make_branch_and_tree('zip')
99
self.build_tree(['zip/a'])
101
self.build_tree_contents([('zip/.bzrrules', '')])
102
tree.add('.bzrrules')
103
self.build_tree(['zip/.bzr-adir/', 'zip/.bzr-adir/afile'])
104
tree.add(['.bzr-adir/', '.bzr-adir/afile'])
107
self.run_bzr('ignore something')
122
self.run_bzr(['init', basedir])
123
self.run_bzr(['export', '--format', 'tgz', u'test.tar.gz',
126
def test_zip_export_ignores_bzr(self):
127
tree = self.make_tree_with_extra_bzr_files()
110
129
self.failUnless(tree.has_filename('.bzrignore'))
111
130
self.failUnless(tree.has_filename('.bzrrules'))
112
131
self.failUnless(tree.has_filename('.bzr-adir'))
113
132
self.failUnless(tree.has_filename('.bzr-adir/afile'))
114
self.run_bzr('export test.zip')
133
self.run_bzr('export test.zip -d tree')
116
135
zfile = zipfile.ZipFile('test.zip')
117
136
# Make sure the zipfile contains 'a', but does not contain
119
138
self.assertEqual(['test/a'], sorted(zfile.namelist()))
140
# TODO: This really looks like something that should be using permutation
141
# testing. Though the actual setup and teardown functions are pretty
143
def assertZipANameAndContent(self, zfile, root=''):
144
"""The file should only contain name 'a' and _file_content"""
146
self.assertEqual([fname], sorted(zfile.namelist()))
148
self.assertEqualDiff(self._file_content, zfile.read(fname))
150
def test_zip_export_stdout(self):
151
tree = self.make_basic_tree()
152
contents = self.run_bzr('export -d tree --format=zip -')[0]
153
self.assertZipANameAndContent(zipfile.ZipFile(StringIO(contents)))
155
def test_zip_export_file(self):
156
tree = self.make_basic_tree()
157
self.run_bzr('export -d tree test.zip')
158
self.assertZipANameAndContent(zipfile.ZipFile('test.zip'),
161
def assertTarANameAndContent(self, ball, root=''):
163
tar_info = ball.next()
164
self.assertEqual(fname, tar_info.name)
165
self.assertEqual(tarfile.REGTYPE, tar_info.type)
166
self.assertEqual(len(self._file_content), tar_info.size)
167
f = ball.extractfile(tar_info)
168
if self._file_content != f.read():
169
self.fail('File content has been corrupted.'
170
' Check that all streams are handled in binary mode.')
171
# There should be no other files in the tarball
172
self.assertIs(None, ball.next())
174
def run_tar_export_disk_and_stdout(self, extension, tarfile_flags):
175
tree = self.make_basic_tree()
176
fname = 'test.%s' % (extension,)
177
mode = 'r|%s' % (tarfile_flags,)
178
self.run_bzr('export -d tree %s' % (fname,))
179
ball = tarfile.open(fname, mode=mode)
180
self.assertTarANameAndContent(ball, root='test/')
181
content = self.run_bzr('export -d tree --format=%s -' % (extension,))[0]
182
ball = tarfile.open(mode=mode, fileobj=StringIO(content))
183
self.assertTarANameAndContent(ball, root='')
185
def test_tar_export(self):
186
self.run_tar_export_disk_and_stdout('tar', '')
188
def test_tgz_export(self):
189
self.run_tar_export_disk_and_stdout('tgz', 'gz')
191
def test_tbz2_export(self):
192
self.run_tar_export_disk_and_stdout('tbz2', 'bz2')
194
# TODO: test_xz_export, I don't have pylzma working here to test it.
121
196
def test_zip_export_unicode(self):
197
self.requireFeature(tests.UnicodeFilenameFeature)
122
198
tree = self.make_branch_and_tree('zip')
123
199
fname = u'\N{Euro Sign}.txt'
125
self.build_tree(['zip/' + fname])
127
raise tests.TestSkipped('Unable to represent path %r' % (fname,))
200
self.build_tree(['zip/' + fname])
128
201
tree.add([fname])
129
202
tree.commit('first')
319
393
self.run_bzr(['export', '--directory=branch', 'latest'])
320
394
self.assertEqual(['goodbye', 'hello'], sorted(os.listdir('latest')))
321
395
self.check_file_contents('latest/goodbye', 'baz')
397
def test_zip_export_per_file_timestamps(self):
398
tree = self.example_branch()
399
self.build_tree_contents([('branch/har', 'foo')])
401
# Earliest allowable date on FAT32 filesystems is 1980-01-01
402
timestamp = 347151600
403
tree.commit('setup', timestamp=timestamp)
404
self.run_bzr('export --per-file-timestamps test.zip branch')
405
zfile = zipfile.ZipFile('test.zip')
406
info = zfile.getinfo("test/har")
407
self.assertEquals(time.localtime(timestamp)[:6], info.date_time)