1
# Copyright (C) 2005 by Canonical Ltd
1
# Copyright (C) 2005, 2006 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
18
17
"""Tests of status command.
20
19
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.
24
from bzrlib.selftest import InTempDir
26
class BranchStatus(InTempDir):
28
"""Basic 'bzr mkdir' operation"""
29
from cStringIO import StringIO
30
from bzrlib.status import show_status
31
from bzrlib.branch import Branch
33
b = Branch('.', init=True)
37
show_status(b, to_file=tof)
38
self.assertEquals(tof.getvalue(), "")
41
self.build_tree(['hello.c', 'bye.c'])
42
show_status(b, to_file=tof)
44
self.assertEquals(tof.readlines(),
25
from cStringIO import StringIO
27
from os import mkdir, chdir, rmdir, unlink
29
from tempfile import TemporaryFile
37
from bzrlib.builtins import merge
38
from bzrlib.osutils import pathjoin
39
from bzrlib.revisionspec import RevisionSpec
40
from bzrlib.status import show_tree_status
41
from bzrlib.tests import TestCaseWithTransport, TestSkipped
42
from bzrlib.workingtree import WorkingTree
45
class BranchStatus(TestCaseWithTransport):
47
def assertStatus(self, expected_lines, working_tree,
48
revision=None, short=False):
49
"""Run status in working_tree and look for output.
51
:param expected_lines: The lines to look for.
52
:param working_tree: The tree to run status in.
54
output_string = self.status_string(working_tree, revision, short)
55
self.assertEqual(expected_lines, output_string.splitlines(True))
57
def status_string(self, wt, revision=None, short=False):
58
# use a real file rather than StringIO because it doesn't handle
60
tof = codecs.getwriter('utf-8')(TemporaryFile())
61
show_tree_status(wt, to_file=tof, revision=revision, short=short)
63
return tof.read().decode('utf-8')
65
def test_branch_status(self):
66
"""Test basic branch status"""
67
wt = self.make_branch_and_tree('.')
69
# status with no commits or files - it must
70
# work and show no output. We do this with no
71
# commits to be sure that it's not going to fail
73
self.assertStatus([], wt)
75
self.build_tree(['hello.c', 'bye.c'])
88
# add a commit to allow showing pending merges.
89
wt.commit('create a parent to allow testing merge output')
91
wt.add_parent_tree_id('pending@pending-0-0')
97
' pending@pending-0-0\n',
103
'P pending@pending-0-0\n',
107
def test_branch_status_revisions(self):
108
"""Tests branch status with revisions"""
109
wt = self.make_branch_and_tree('.')
111
self.build_tree(['hello.c', 'bye.c'])
114
wt.commit('Test message')
116
revs = [RevisionSpec.from_string('0')]
125
self.build_tree(['more.c'])
127
wt.commit('Another test message')
129
revs.append(RevisionSpec.from_string('1'))
138
def test_pending(self):
139
"""Pending merges display works, including Unicode"""
141
wt = self.make_branch_and_tree('branch')
143
wt.commit("Empty commit 1")
144
b_2_dir = b.bzrdir.sprout('./copy')
145
b_2 = b_2_dir.open_branch()
146
wt2 = b_2_dir.open_workingtree()
147
wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
148
merge(["./branch", -1], [None, None], this_dir = './copy')
149
message = self.status_string(wt2)
150
self.assertStartsWith(message, "pending merges:\n")
151
self.assertEndsWith(message, "Empty commit 2\n")
153
# must be long to make sure we see elipsis at the end
154
wt.commit("Empty commit 3 " +
155
"blah blah blah blah " * 100)
156
merge(["./branch", -1], [None, None], this_dir = './copy')
157
message = self.status_string(wt2)
158
self.assertStartsWith(message, "pending merges:\n")
159
self.assert_("Empty commit 3" in message)
160
self.assertEndsWith(message, "...\n")
162
def test_tree_status_ignores(self):
163
"""Tests branch status with ignores"""
164
wt = self.make_branch_and_tree('.')
165
self.run_bzr('ignore *~')
166
wt.commit('commit .bzrignore')
167
self.build_tree(['foo.c', 'foo.c~'])
178
def test_tree_status_specific_files(self):
179
"""Tests branch status with given specific files"""
180
wt = self.make_branch_and_tree('.')
183
self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
192
' directory/hello.c\n'
199
'? directory/hello.c\n'
204
self.assertRaises(errors.PathsDoNotExist,
206
wt, specific_files=['bye.c','test.c','absent.c'],
210
show_tree_status(wt, specific_files=['directory'], to_file=tof)
212
self.assertEquals(tof.readlines(),
214
' directory/hello.c\n'
217
show_tree_status(wt, specific_files=['directory'], to_file=tof,
220
self.assertEquals(tof.readlines(), ['? directory/hello.c\n'])
223
show_tree_status(wt, specific_files=['dir2'], to_file=tof)
225
self.assertEquals(tof.readlines(),
230
show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
232
self.assertEquals(tof.readlines(), ['? dir2/\n'])
234
def test_specific_files_conflicts(self):
235
tree = self.make_branch_and_tree('.')
236
self.build_tree(['dir2/'])
238
tree.commit('added dir2')
239
tree.set_conflicts(conflicts.ConflictList(
240
[conflicts.ContentsConflict('foo')]))
242
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
243
self.assertEqualDiff('', tof.getvalue())
244
tree.set_conflicts(conflicts.ConflictList(
245
[conflicts.ContentsConflict('dir2')]))
247
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
248
self.assertEqualDiff('conflicts:\n Contents conflict in dir2\n',
251
tree.set_conflicts(conflicts.ConflictList(
252
[conflicts.ContentsConflict('dir2/file1')]))
254
show_tree_status(tree, specific_files=['dir2'], to_file=tof)
255
self.assertEqualDiff('conflicts:\n Contents conflict in dir2/file1\n',
258
def test_status_nonexistent_file(self):
259
# files that don't exist in either the basis tree or working tree
260
# should give an error
261
wt = self.make_branch_and_tree('.')
262
out, err = self.run_bzr('status does-not-exist', retcode=3)
263
self.assertContainsRe(err, r'do not exist.*does-not-exist')
265
def test_status_out_of_date(self):
266
"""Simulate status of out-of-date tree after remote push"""
267
tree = self.make_branch_and_tree('.')
268
self.build_tree_contents([('a', 'foo\n')])
272
tree.commit('add test file')
273
# simulate what happens after a remote push
274
tree.set_last_revision("0")
276
# before run another commands we should unlock tree
278
out, err = self.run_bzr('status')
279
self.assertEqual("working tree is out of date, run 'bzr update'\n",
283
class CheckoutStatus(BranchStatus):
286
super(CheckoutStatus, self).setUp()
290
def make_branch_and_tree(self, relpath):
291
source = self.make_branch(pathjoin('..', relpath))
292
checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
293
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
294
return checkout.create_workingtree()
297
class TestStatus(TestCaseWithTransport):
299
def test_status_plain(self):
302
self.build_tree(['hello.txt'])
303
result = self.run_bzr("status")[0]
304
self.assertContainsRe(result, "unknown:\n hello.txt\n")
306
self.run_bzr("add hello.txt")
307
result = self.run_bzr("status")[0]
308
self.assertContainsRe(result, "added:\n hello.txt\n")
310
self.run_bzr("commit -m added")
311
result = self.run_bzr("status -r 0..1")[0]
312
self.assertContainsRe(result, "added:\n hello.txt\n")
314
self.build_tree(['world.txt'])
315
result = self.run_bzr("status -r 0")[0]
316
self.assertContainsRe(result, "added:\n hello.txt\n" \
317
"unknown:\n world.txt\n")
318
result2 = self.run_bzr("status -r 0..")[0]
319
self.assertEquals(result2, result)
321
def test_status_short(self):
324
self.build_tree(['hello.txt'])
325
result = self.run_bzr("status --short")[0]
326
self.assertContainsRe(result, "[?] hello.txt\n")
328
self.run_bzr("add hello.txt")
329
result = self.run_bzr("status --short")[0]
330
self.assertContainsRe(result, "[+]N hello.txt\n")
332
self.run_bzr("commit -m added")
333
result = self.run_bzr("status --short -r 0..1")[0]
334
self.assertContainsRe(result, "[+]N hello.txt\n")
336
self.build_tree(['world.txt'])
337
result = self.run_bzr("status --short -r 0")[0]
338
self.assertContainsRe(result, "[+]N hello.txt\n" \
340
result2 = self.run_bzr("status --short -r 0..")[0]
341
self.assertEquals(result2, result)
343
def test_status_versioned(self):
346
self.build_tree(['hello.txt'])
347
result = self.run_bzr("status --versioned")[0]
348
self.assertNotContainsRe(result, "unknown:\n hello.txt\n")
350
self.run_bzr("add hello.txt")
351
result = self.run_bzr("status --versioned")[0]
352
self.assertContainsRe(result, "added:\n hello.txt\n")
354
self.run_bzr("commit -m added")
355
result = self.run_bzr("status --versioned -r 0..1")[0]
356
self.assertContainsRe(result, "added:\n hello.txt\n")
358
self.build_tree(['world.txt'])
359
result = self.run_bzr("status --versioned -r 0")[0]
360
self.assertContainsRe(result, "added:\n hello.txt\n")
361
self.assertNotContainsRe(result, "unknown:\n world.txt\n")
362
result2 = self.run_bzr("status --versioned -r 0..")[0]
363
self.assertEquals(result2, result)
365
def assertStatusContains(self, pattern):
366
"""Run status, and assert it contains the given pattern"""
367
result = self.run_bzr("status --short")[0]
368
self.assertContainsRe(result, pattern)
370
def test_kind_change_short(self):
371
tree = self.make_branch_and_tree('.')
372
self.build_tree(['file'])
374
tree.commit('added file')
376
self.build_tree(['file/'])
377
self.assertStatusContains('K file => file/')
378
tree.rename_one('file', 'directory')
379
self.assertStatusContains('RK file => directory/')
381
self.assertStatusContains('RD file => directory')
384
class TestStatusEncodings(TestCaseWithTransport):
387
TestCaseWithTransport.setUp(self)
388
self.user_encoding = bzrlib.user_encoding
389
self.stdout = sys.stdout
392
bzrlib.user_encoding = self.user_encoding
393
sys.stdout = self.stdout
394
TestCaseWithTransport.tearDown(self)
396
def make_uncommitted_tree(self):
397
"""Build a branch with uncommitted unicode named changes in the cwd."""
398
working_tree = self.make_branch_and_tree(u'.')
399
filename = u'hell\u00d8'
401
self.build_tree_contents([(filename, 'contents of hello')])
402
except UnicodeEncodeError:
403
raise TestSkipped("can't build unicode working tree in "
404
"filesystem encoding %s" % sys.getfilesystemencoding())
405
working_tree.add(filename)
408
def test_stdout_ascii(self):
409
sys.stdout = StringIO()
410
bzrlib.user_encoding = 'ascii'
411
working_tree = self.make_uncommitted_tree()
412
stdout, stderr = self.run_bzr("status")
414
self.assertEquals(stdout, """\
419
def test_stdout_latin1(self):
420
sys.stdout = StringIO()
421
bzrlib.user_encoding = 'latin-1'
422
working_tree = self.make_uncommitted_tree()
423
stdout, stderr = self.run_bzr('status')
425
self.assertEquals(stdout, u"""\
428
""".encode('latin-1'))