1
# Copyright (C) 2005, 2006 Canonical Ltd
1
# Copyright (C) 2005 by Canonical Ltd
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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
"""Tests of status command.
19
20
Most of these depend on the particular formatting used.
20
As such they really are blackbox tests even though some of the
21
tests are not using self.capture. If we add tests for the programmatic
22
interface later, they will be non blackbox tests.
25
from cStringIO import StringIO
27
from os import mkdir, chdir, rmdir, unlink
29
from tempfile import TemporaryFile
37
from bzrlib.osutils import pathjoin
38
from bzrlib.revisionspec import RevisionSpec
39
from bzrlib.status import show_tree_status
40
from bzrlib.tests import TestCaseWithTransport, TestSkipped
41
from bzrlib.workingtree import WorkingTree
44
class BranchStatus(TestCaseWithTransport):
46
def assertStatus(self, expected_lines, working_tree,
47
revision=None, short=False):
48
"""Run status in working_tree and look for output.
50
:param expected_lines: The lines to look for.
51
:param working_tree: The tree to run status in.
53
output_string = self.status_string(working_tree, revision, short)
54
self.assertEqual(expected_lines, output_string.splitlines(True))
56
def status_string(self, wt, revision=None, short=False):
57
# use a real file rather than StringIO because it doesn't handle
59
tof = codecs.getwriter('utf-8')(TemporaryFile())
60
show_tree_status(wt, to_file=tof, revision=revision, short=short)
62
return tof.read().decode('utf-8')
64
def test_branch_status(self):
65
"""Test basic branch status"""
66
wt = self.make_branch_and_tree('.')
68
# status with no commits or files - it must
69
# work and show no output. We do this with no
70
# commits to be sure that it's not going to fail
72
self.assertStatus([], wt)
74
self.build_tree(['hello.c', 'bye.c'])
87
# add a commit to allow showing pending merges.
88
wt.commit('create a parent to allow testing merge output')
90
wt.add_parent_tree_id('pending@pending-0-0')
96
' pending@pending-0-0\n',
102
'P pending@pending-0-0\n',
106
def test_branch_status_revisions(self):
107
"""Tests branch status with revisions"""
108
wt = self.make_branch_and_tree('.')
110
self.build_tree(['hello.c', 'bye.c'])
113
wt.commit('Test message')
115
revs = [RevisionSpec.from_string('0')]
124
self.build_tree(['more.c'])
126
wt.commit('Another test message')
128
revs.append(RevisionSpec.from_string('1'))
137
def test_pending(self):
138
"""Pending merges display works, including Unicode"""
140
wt = self.make_branch_and_tree('branch')
142
wt.commit("Empty commit 1")
143
b_2_dir = b.bzrdir.sprout('./copy')
144
b_2 = b_2_dir.open_branch()
145
wt2 = b_2_dir.open_workingtree()
146
wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
147
wt2.merge_from_branch(wt.branch)
148
message = self.status_string(wt2)
149
self.assertStartsWith(message, "pending merges:\n")
150
self.assertEndsWith(message, "Empty commit 2\n")
152
# must be long to make sure we see elipsis at the end
153
wt.commit("Empty commit 3 " +
154
"blah blah blah blah " * 100)
155
wt2.merge_from_branch(wt.branch)
156
message = self.status_string(wt2)
157
self.assertStartsWith(message, "pending merges:\n")
158
self.assert_("Empty commit 3" in message)
159
self.assertEndsWith(message, "...\n")
161
def test_tree_status_ignores(self):
162
"""Tests branch status with ignores"""
163
wt = self.make_branch_and_tree('.')
164
self.run_bzr('ignore *~')
165
wt.commit('commit .bzrignore')
166
self.build_tree(['foo.c', 'foo.c~'])
177
def test_tree_status_specific_files(self):
178
"""Tests branch status with given specific files"""
179
wt = self.make_branch_and_tree('.')
182
self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
191
' directory/hello.c\n'
198
'? directory/hello.c\n'
203
self.assertRaises(errors.PathsDoNotExist,
205
wt, specific_files=['bye.c','test.c','absent.c'],
209
show_tree_status(wt, specific_files=['directory'], to_file=tof)
211
self.assertEquals(tof.readlines(),
213
' directory/hello.c\n'
216
show_tree_status(wt, specific_files=['directory'], to_file=tof,
219
self.assertEquals(tof.readlines(), ['? directory/hello.c\n'])
222
show_tree_status(wt, specific_files=['dir2'], to_file=tof)
224
self.assertEquals(tof.readlines(),
229
show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
231
self.assertEquals(tof.readlines(), ['? dir2/\n'])
234
revs = [RevisionSpec.from_string('0'), RevisionSpec.from_string('1')]
235
show_tree_status(wt, specific_files=['test.c'], to_file=tof,
236
short=True, revision=revs)
238
self.assertEquals(tof.readlines(), ['+N test.c\n'])
240
def test_specific_files_conflicts(self):
241
tree = self.make_branch_and_tree('.')
242
self.build_tree(['dir2/'])
244
tree.commit('added dir2')
245
tree.set_conflicts(conflicts.ConflictList(
246
[conflicts.ContentsConflict('foo')]))
248
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
249
self.assertEqualDiff('', tof.getvalue())
250
tree.set_conflicts(conflicts.ConflictList(
251
[conflicts.ContentsConflict('dir2')]))
253
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
254
self.assertEqualDiff('conflicts:\n Contents conflict in dir2\n',
257
tree.set_conflicts(conflicts.ConflictList(
258
[conflicts.ContentsConflict('dir2/file1')]))
260
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
261
self.assertEqualDiff('conflicts:\n Contents conflict in dir2/file1\n',
264
def test_status_nonexistent_file(self):
265
# files that don't exist in either the basis tree or working tree
266
# should give an error
267
wt = self.make_branch_and_tree('.')
268
out, err = self.run_bzr('status does-not-exist', retcode=3)
269
self.assertContainsRe(err, r'do not exist.*does-not-exist')
271
def test_status_out_of_date(self):
272
"""Simulate status of out-of-date tree after remote push"""
273
tree = self.make_branch_and_tree('.')
274
self.build_tree_contents([('a', 'foo\n')])
278
tree.commit('add test file')
279
# simulate what happens after a remote push
280
tree.set_last_revision("0")
282
# before run another commands we should unlock tree
284
out, err = self.run_bzr('status')
285
self.assertEqual("working tree is out of date, run 'bzr update'\n",
289
class CheckoutStatus(BranchStatus):
292
super(CheckoutStatus, self).setUp()
296
def make_branch_and_tree(self, relpath):
297
source = self.make_branch(pathjoin('..', relpath))
298
checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
299
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
300
return checkout.create_workingtree()
303
class TestStatus(TestCaseWithTransport):
305
def test_status_plain(self):
306
tree = self.make_branch_and_tree('.')
308
self.build_tree(['hello.txt'])
309
result = self.run_bzr("status")[0]
310
self.assertContainsRe(result, "unknown:\n hello.txt\n")
312
tree.add("hello.txt")
313
result = self.run_bzr("status")[0]
314
self.assertContainsRe(result, "added:\n hello.txt\n")
316
tree.commit(message="added")
317
result = self.run_bzr("status -r 0..1")[0]
318
self.assertContainsRe(result, "added:\n hello.txt\n")
320
result = self.run_bzr("status -c 1")[0]
321
self.assertContainsRe(result, "added:\n hello.txt\n")
323
self.build_tree(['world.txt'])
324
result = self.run_bzr("status -r 0")[0]
325
self.assertContainsRe(result, "added:\n hello.txt\n" \
326
"unknown:\n world.txt\n")
327
result2 = self.run_bzr("status -r 0..")[0]
328
self.assertEquals(result2, result)
330
def test_status_short(self):
331
tree = self.make_branch_and_tree('.')
333
self.build_tree(['hello.txt'])
334
result = self.run_bzr("status --short")[0]
335
self.assertContainsRe(result, "[?] hello.txt\n")
337
tree.add("hello.txt")
338
result = self.run_bzr("status --short")[0]
339
self.assertContainsRe(result, "[+]N hello.txt\n")
341
tree.commit(message="added")
342
result = self.run_bzr("status --short -r 0..1")[0]
343
self.assertContainsRe(result, "[+]N hello.txt\n")
345
self.build_tree(['world.txt'])
346
result = self.run_bzr("status --short -r 0")[0]
347
self.assertContainsRe(result, "[+]N hello.txt\n" \
349
result2 = self.run_bzr("status --short -r 0..")[0]
350
self.assertEquals(result2, result)
352
def test_status_versioned(self):
353
tree = self.make_branch_and_tree('.')
355
self.build_tree(['hello.txt'])
356
result = self.run_bzr("status --versioned")[0]
357
self.assertNotContainsRe(result, "unknown:\n hello.txt\n")
359
tree.add("hello.txt")
360
result = self.run_bzr("status --versioned")[0]
361
self.assertContainsRe(result, "added:\n hello.txt\n")
364
result = self.run_bzr("status --versioned -r 0..1")[0]
365
self.assertContainsRe(result, "added:\n hello.txt\n")
367
self.build_tree(['world.txt'])
368
result = self.run_bzr("status --versioned -r 0")[0]
369
self.assertContainsRe(result, "added:\n hello.txt\n")
370
self.assertNotContainsRe(result, "unknown:\n world.txt\n")
371
result2 = self.run_bzr("status --versioned -r 0..")[0]
372
self.assertEquals(result2, result)
374
def test_status_SV(self):
375
tree = self.make_branch_and_tree('.')
377
self.build_tree(['hello.txt'])
378
result = self.run_bzr("status -SV")[0]
379
self.assertNotContainsRe(result, "hello.txt")
381
tree.add("hello.txt")
382
result = self.run_bzr("status -SV")[0]
383
self.assertContainsRe(result, "[+]N hello.txt\n")
385
tree.commit(message="added")
386
result = self.run_bzr("status -SV -r 0..1")[0]
387
self.assertContainsRe(result, "[+]N hello.txt\n")
389
self.build_tree(['world.txt'])
390
result = self.run_bzr("status -SV -r 0")[0]
391
self.assertContainsRe(result, "[+]N hello.txt\n")
393
result2 = self.run_bzr("status -SV -r 0..")[0]
394
self.assertEquals(result2, result)
396
def assertStatusContains(self, pattern):
397
"""Run status, and assert it contains the given pattern"""
398
result = self.run_bzr("status --short")[0]
399
self.assertContainsRe(result, pattern)
401
def test_kind_change_short(self):
402
tree = self.make_branch_and_tree('.')
403
self.build_tree(['file'])
405
tree.commit('added file')
407
self.build_tree(['file/'])
408
self.assertStatusContains('K file => file/')
409
tree.rename_one('file', 'directory')
410
self.assertStatusContains('RK file => directory/')
412
self.assertStatusContains('RD file => directory')
414
def test_status_illegal_revision_specifiers(self):
415
out, err = self.run_bzr('status -r 1..23..123', retcode=3)
416
self.assertContainsRe(err, 'one or two revision specifiers')
419
class TestStatusEncodings(TestCaseWithTransport):
422
TestCaseWithTransport.setUp(self)
423
self.user_encoding = bzrlib.user_encoding
424
self.stdout = sys.stdout
427
bzrlib.user_encoding = self.user_encoding
428
sys.stdout = self.stdout
429
TestCaseWithTransport.tearDown(self)
431
def make_uncommitted_tree(self):
432
"""Build a branch with uncommitted unicode named changes in the cwd."""
433
working_tree = self.make_branch_and_tree(u'.')
434
filename = u'hell\u00d8'
436
self.build_tree_contents([(filename, 'contents of hello')])
437
except UnicodeEncodeError:
438
raise TestSkipped("can't build unicode working tree in "
439
"filesystem encoding %s" % sys.getfilesystemencoding())
440
working_tree.add(filename)
443
def test_stdout_ascii(self):
444
sys.stdout = StringIO()
445
bzrlib.user_encoding = 'ascii'
446
working_tree = self.make_uncommitted_tree()
447
stdout, stderr = self.run_bzr("status")
449
self.assertEquals(stdout, """\
454
def test_stdout_latin1(self):
455
sys.stdout = StringIO()
456
bzrlib.user_encoding = 'latin-1'
457
working_tree = self.make_uncommitted_tree()
458
stdout, stderr = self.run_bzr('status')
460
self.assertEquals(stdout, u"""\
463
""".encode('latin-1'))
24
from bzrlib.selftest import TestCaseInTempDir
26
class BranchStatus(TestCaseInTempDir):
28
def test_branch_status(self):
29
"""Basic 'bzr mkdir' operation"""
30
from cStringIO import StringIO
31
from bzrlib.status import show_status
32
from bzrlib.branch import Branch
34
b = Branch('.', init=True)
38
show_status(b, to_file=tof)
39
self.assertEquals(tof.getvalue(), "")
42
self.build_tree(['hello.c', 'bye.c'])
43
b.add_pending_merge('pending@pending-0-0')
44
show_status(b, to_file=tof)
46
self.assertEquals(tof.readlines(),
51
' pending@pending-0-0\n'