1
# Copyright (C) 2006 by Canonical Ltd
2
# -*- coding: utf-8 -*-
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
Black-box tests for bzr handling non-ascii characters.
25
from bzrlib.tests import TestCaseInTempDir, TestSkipped
26
from bzrlib.trace import mutter, note
29
class TestNonAscii(TestCaseInTempDir):
30
"""Test that bzr handles files/committers/etc which are non-ascii."""
33
super(TestNonAscii, self).setUp()
34
raise TestSkipped('We cannot handle unicode filenames (yet)')
35
# TODO: jam 20060425 because of the confusion of URLs versus Unicode
36
# 'bzr add f' will not add a unicode filename
37
self._orig_email = os.environ.get('BZREMAIL', None)
38
self._orig_encoding = bzrlib.user_encoding
40
bzrlib.user_encoding = self.encoding
41
email = self.info['committer'] + ' <joe@foo.com>'
42
os.environ['BZREMAIL'] = email.encode(bzrlib.user_encoding)
46
if self._orig_email is not None:
47
os.environ['BZREMAIL'] = self._orig_email
49
if os.environ.get('BZREMAIL', None) is not None:
50
del os.environ['BZREMAIL']
51
bzrlib.user_encoding = self._orig_encoding
52
super(TestNonAscii, self).tearDown()
54
def create_base(self):
58
open('a', 'wb').write('foo\n')
60
bzr('commit', '-m', 'adding a')
62
open('b', 'wb').write('non-ascii \xFF\xFF\xFC\xFB\x00 in b\n')
64
bzr('commit', '-m', self.info['message'])
66
fname = self.info['filename']
68
open(fname, 'wb').write('unicode filename\n')
69
except UnicodeEncodeError:
70
raise TestSkipped(('Unable to represent filename %r'
71
' in filesystem encoding %s')
72
% (fname, sys.getfilesystemencoding()))
75
bzr('commit', '-m', u'And an unicode file\n')
77
def test_status(self):
78
bzr = self.run_bzr_decode
80
open(self.info['filename'], 'ab').write('added something\n')
82
self.assertEqual(u'modified:\n %s\n' % (self.info['filename'],), txt)
85
# bzr cat shouldn't change the contents
86
# using run_bzr since that doesn't decode
87
txt = self.run_bzr('cat', 'b')[0]
88
self.assertEqual('non-ascii \xFF\xFF\xFC\xFB\x00 in b\n', txt)
90
txt = self.run_bzr('cat', self.info['filename'])[0]
91
self.assertEqual('unicode filename\n', txt)
93
def test_cat_revision(self):
94
bzr = self.run_bzr_decode
96
# TODO: jam 20060112 should cat-revision always output utf-8?
97
committer = self.info['committer']
98
txt = bzr('cat-revision', '-r', '1')
99
self.failUnless(committer in txt,
100
'failed to find %r in %r' % (committer, txt))
102
msg = self.info['message']
103
txt = bzr('cat-revision', '-r', '2')
104
self.failUnless(msg in txt, 'failed to find %r in %r' % (msg, txt))
106
def test_mkdir(self):
107
bzr = self.run_bzr_decode
109
txt = bzr('mkdir', self.info['directory'])
110
self.assertEqual(u'added %s\n' % self.info['directory'], txt)
112
# The text should be garbled, but the command should succeed
113
txt = bzr('mkdir', self.info['directory'] + '2', encoding='ascii')
114
expected = u'added %s2\n' % (self.info['directory'],)
115
expected = expected.encode('ascii', 'replace')
116
self.assertEqual(expected, txt)
118
def test_relpath(self):
119
bzr = self.run_bzr_decode
121
txt = bzr('relpath', self.info['filename'])
122
self.assertEqual(self.info['filename'] + '\n', txt)
124
# TODO: jam 20060106 if relpath can return a munged string
125
# this text needs to be fixed
126
bzr('relpath', self.info['filename'], encoding='ascii', retcode=3)
128
def test_inventory(self):
129
bzr = self.run_bzr_decode
131
txt = bzr('inventory')
132
self.assertEqual(['a', 'b', self.info['filename']],
135
# inventory should fail if unable to encode
136
bzr('inventory', encoding='ascii', retcode=3)
138
# We don't really care about the ids themselves,
139
# but the command shouldn't fail
140
txt = bzr('inventory', '--show-ids')
142
def test_revno(self):
143
# There isn't a lot to test here, since revno should always
145
bzr = self.run_bzr_decode
147
self.assertEqual('3\n', bzr('revno'))
148
self.assertEqual('3\n', bzr('revno', encoding='ascii'))
150
def test_revision_info(self):
151
bzr = self.run_bzr_decode
153
bzr('revision-info', '-r', '1')
155
# TODO: jam 20060105 We have no revisions with non-ascii characters.
156
bzr('revision-info', '-r', '1', encoding='ascii')
159
bzr = self.run_bzr_decode
161
fname1 = self.info['filename']
162
fname2 = self.info['filename'] + '2'
163
dirname = self.info['directory']
165
bzr('mv', 'a', fname1, retcode=3)
167
txt = bzr('mv', 'a', fname2)
168
self.assertEqual(u'a => %s\n' % fname2, txt)
169
self.failIfExists('a')
170
self.failUnlessExists(fname2)
172
bzr('commit', '-m', 'renamed to non-ascii')
174
bzr('mkdir', dirname)
175
txt = bzr('mv', fname1, fname2, dirname)
176
self.assertEqual([u'%s => %s/%s' % (fname1, dirname, fname1),
177
u'%s => %s/%s' % (fname2, dirname, fname2)]
180
# The rename should still succeed
181
newpath = u'%s/%s' % (dirname, fname2)
182
txt = bzr('mv', newpath, 'a', encoding='ascii')
183
self.failUnlessExists('a')
184
self.assertEqual(newpath.encode('ascii', 'replace'), txt)
186
def test_branch(self):
187
# We should be able to branch into a directory that
188
# has a unicode name, even if we can't display the name
189
bzr = self.run_bzr_decode
191
bzr('branch', u'.', self.info['directory'])
193
bzr('branch', u'.', self.info['directory'] + '2', encoding='ascii')
196
# Make sure we can pull from paths that can't be encoded
197
bzr = self.run_bzr_decode
199
dirname1 = self.info['directory']
200
dirname2 = self.info['directory'] + '2'
201
bzr('branch', '.', dirname1)
202
bzr('branch', dirname1, dirname2)
205
open('a', 'ab').write('more text\n')
206
bzr('commit', '-m', 'mod a')
210
os.chdir(u'../' + dirname2)
213
self.assertEqual(u'Using saved location: %s\n' % (pwd,), txt)
215
os.chdir('../' + dirname1)
216
open('a', 'ab').write('and yet more\n')
217
bzr('commit', '-m', 'modifying a by ' + self.info['committer'])
219
os.chdir('../' + dirname2)
220
# We should be able to pull, even if our encoding is bad
221
bzr('pull', '--verbose', encoding='ascii')
224
# TODO: Test push to an SFTP location
225
# Make sure we can pull from paths that can't be encoded
226
bzr = self.run_bzr_decode
228
dirname = self.info['directory']
231
open('a', 'ab').write('adding more text\n')
232
bzr('commit', '-m', 'added some stuff')
237
f.write('and a bit more: ')
238
f.write(dirname.encode('utf-8'))
242
bzr('commit', '-m', u'Added some ' + dirname)
243
bzr('push', '--verbose', encoding='ascii')
245
bzr('push', '--verbose', dirname + '2')
247
bzr('push', '--verbose', dirname + '3', encoding='ascii')
249
def test_renames(self):
250
bzr = self.run_bzr_decode
252
fname = self.info['filename'] + '2'
253
bzr('mv', 'a', fname)
255
self.assertEqual(u'a => %s\n' % fname, txt)
257
bzr('renames', retcode=3, encoding='ascii')
259
def test_remove(self):
260
bzr = self.run_bzr_decode
262
fname = self.info['filename']
263
txt = bzr('remove', fname, encoding='ascii')
265
def test_remove_verbose(self):
266
bzr = self.run_bzr_decode
268
raise TestSkipped('bzr remove --verbose uses tree.remove, which calls print directly.')
269
fname = self.info['filename']
270
txt = bzr('remove', '--verbose', fname, encoding='ascii')
272
def test_file_id(self):
273
bzr = self.run_bzr_decode
275
fname = self.info['filename']
276
txt = bzr('file-id', fname)
278
# TODO: jam 20060106 We don't support non-ascii file ids yet,
279
# so there is nothing which would fail in ascii encoding
280
# This *should* be retcode=3
281
txt = bzr('file-id', fname, encoding='ascii')
283
def test_file_path(self):
284
bzr = self.run_bzr_decode
286
# Create a directory structure
287
fname = self.info['filename']
288
dirname = self.info['directory']
290
bzr('mkdir', 'base/' + dirname)
291
path = '/'.join(['base', dirname, fname])
292
bzr('mv', fname, path)
293
bzr('commit', '-m', 'moving things around')
295
txt = bzr('file-path', path)
297
# TODO: jam 20060106 We don't support non-ascii file ids yet,
298
# so there is nothing which would fail in ascii encoding
299
# This *should* be retcode=3
300
txt = bzr('file-path', path, encoding='ascii')
302
def test_revision_history(self):
303
bzr = self.run_bzr_decode
305
# TODO: jam 20060106 We don't support non-ascii revision ids yet,
306
# so there is nothing which would fail in ascii encoding
307
txt = bzr('revision-history')
309
def test_ancestry(self):
310
bzr = self.run_bzr_decode
312
# TODO: jam 20060106 We don't support non-ascii revision ids yet,
313
# so there is nothing which would fail in ascii encoding
314
txt = bzr('ancestry')
317
# TODO: jam 20060106 diff is a difficult one to test, because it
318
# shouldn't encode the file contents, but it needs some sort
319
# of encoding for the paths, etc which are displayed.
322
def test_deleted(self):
323
bzr = self.run_bzr_decode
325
fname = self.info['filename']
330
self.assertEqual(fname+'\n', txt)
332
txt = bzr('deleted', '--show-ids')
333
self.failUnless(txt.startswith(fname))
335
# Deleted should fail if cannot decode
336
# Because it is giving the exact paths
337
# which might be used by a front end
338
bzr('deleted', encoding='ascii', retcode=3)
340
def test_modified(self):
341
bzr = self.run_bzr_decode
343
fname = self.info['filename']
344
open(fname, 'ab').write('modified\n')
346
txt = bzr('modified')
347
self.assertEqual(fname+'\n', txt)
349
bzr('modified', encoding='ascii', retcode=3)
351
def test_added(self):
352
bzr = self.run_bzr_decode
354
fname = self.info['filename'] + '2'
355
open(fname, 'wb').write('added\n')
359
self.assertEqual(fname+'\n', txt)
361
bzr('added', encoding='ascii', retcode=3)
364
bzr = self.run_bzr_decode
366
dirname = self.info['directory']
369
bzr('branch', u'.', dirname)
374
self.failUnless(txt.endswith(dirname+'\n'))
376
txt = bzr('root', encoding='ascii', retcode=3)
379
bzr = self.run_bzr_decode
381
fname = self.info['filename']
384
self.assertNotEqual(-1, txt.find(self.info['committer']))
385
self.assertNotEqual(-1, txt.find(self.info['message']))
387
txt = bzr('log', '--verbose')
388
self.assertNotEqual(-1, txt.find(fname))
390
# Make sure log doesn't fail even if we can't write out
391
txt = bzr('log', '--verbose', encoding='ascii')
392
self.assertEqual(-1, txt.find(fname))
393
self.assertNotEqual(-1, txt.find(fname.encode('ascii', 'replace')))
395
def test_touching_revisions(self):
396
bzr = self.run_bzr_decode
398
fname = self.info['filename']
399
txt = bzr('touching-revisions', fname)
400
self.assertEqual(u' 3 added %s\n' % (fname,), txt)
402
fname2 = self.info['filename'] + '2'
403
bzr('mv', fname, fname2)
404
bzr('commit', '-m', u'Renamed %s => %s' % (fname, fname2))
406
txt = bzr('touching-revisions', fname2)
407
expected_txt = (u' 3 added %s\n'
408
u' 4 renamed %s => %s\n'
409
% (fname, fname, fname2))
410
self.assertEqual(expected_txt, txt)
412
txt = bzr('touching-revisions', fname2, encoding='ascii')
413
expected_ascii = expected_txt.encode('ascii', 'replace')
414
self.assertEqual(expected_ascii, txt)
417
bzr = self.run_bzr_decode
420
self.assertEqual(['a', 'b', self.info['filename']],
422
txt = bzr('ls', '--null')
423
self.assertEqual(['a', 'b', self.info['filename'], ''],
426
txt = bzr('ls', encoding='ascii', retcode=3)
427
txt = bzr('ls', '--null', encoding='ascii', retcode=3)
429
def test_unknowns(self):
430
bzr = self.run_bzr_decode
432
fname = self.info['filename'] + '2'
433
open(fname, 'wb').write('unknown\n')
435
# TODO: jam 20060112 bzr unknowns is the only one which
436
# quotes paths do we really want it to?
437
txt = bzr('unknowns')
438
self.assertEqual(u'"%s"\n' % (fname,), txt)
440
bzr('unknowns', encoding='ascii', retcode=3)
442
def test_ignore(self):
443
bzr = self.run_bzr_decode
445
fname2 = self.info['filename'] + '2.txt'
446
open(fname2, 'wb').write('ignored\n')
448
txt = bzr('unknowns')
449
self.assertEqual(u'"%s"\n' % (fname2,), txt)
451
bzr('ignore', './' + fname2)
452
txt = bzr('unknowns')
453
# TODO: jam 20060107 This is the correct output
454
# self.assertEqual('', txt)
455
# This is the incorrect output
456
self.assertEqual(u'"%s"\n' % (fname2,), txt)
458
fname3 = self.info['filename'] + '3.txt'
459
open(fname3, 'wb').write('unknown 3\n')
460
txt = bzr('unknowns')
461
# TODO: jam 20060107 This is the correct output
462
# self.assertEqual(u'"%s"\n' % (fname3,), txt)
463
# This is the incorrect output
464
self.assertEqual(u'"%s"\n"%s"\n' % (fname2, fname3,), txt)
466
# Ignore should not care what the encoding is
467
# (right now it doesn't print anything)
468
bzr('ignore', fname3, encoding='ascii')
469
txt = bzr('unknowns')
470
# TODO: jam 20060107 This is the correct output
471
# self.assertEqual('', txt)
472
# This is the incorrect output
473
self.assertEqual(u'"%s"\n"%s"\n' % (fname2, fname3), txt)
475
# Now try a wildcard match
476
fname4 = self.info['filename'] + '4.txt'
477
open(fname4, 'wb').write('unknown 4\n')
478
bzr('ignore', '*.txt')
479
txt = bzr('unknowns')
480
self.assertEqual('', txt)
482
os.remove('.bzrignore')
483
bzr('ignore', self.info['filename'] + '*')
484
txt = bzr('unknowns')
485
# TODO: jam 20060107 This is the correct output
486
# self.assertEqual('', txt)
487
# This is the incorrect output
488
self.assertEqual(u'"%s"\n"%s"\n"%s"\n' % (fname2, fname3, fname4), txt)
490
# TODO: jam 20060107 The best error we have right now is TestSkipped
491
# to indicate that this test is known to fail
492
raise TestSkipped("WorkingTree.is_ignored doesn't match unicode filenames (yet)")