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
31
from bzrlib import bzrdir, errors
33
from bzrlib.builtins import merge
34
from bzrlib.osutils import pathjoin
35
from bzrlib.revisionspec import RevisionSpec
36
from bzrlib.status import show_tree_status
37
from bzrlib.tests import TestCaseWithTransport, TestSkipped
38
from bzrlib.workingtree import WorkingTree
41
class BranchStatus(TestCaseWithTransport):
43
def assertStatus(self, expected_lines, working_tree,
44
revision=None, short=False):
45
"""Run status in working_tree and look for output.
47
:param expected_lines: The lines to look for.
48
:param working_tree: The tree to run status in.
50
output_string = self.status_string(working_tree, revision, short)
51
self.assertEqual(expected_lines, output_string.splitlines(True))
53
def status_string(self, wt, revision=None, short=False):
54
# use a real file rather than StringIO because it doesn't handle
56
tof = codecs.getwriter('utf-8')(TemporaryFile())
57
show_tree_status(wt, to_file=tof, revision=revision, short=short)
59
return tof.read().decode('utf-8')
61
def test_branch_status(self):
62
"""Test basic branch status"""
63
wt = self.make_branch_and_tree('.')
65
# status with no commits or files - it must
66
# work and show no output. We do this with no
67
# commits to be sure that it's not going to fail
69
self.assertStatus([], wt)
71
self.build_tree(['hello.c', 'bye.c'])
84
# add a commit to allow showing pending merges.
85
wt.commit('create a parent to allow testing merge output')
87
wt.add_parent_tree_id('pending@pending-0-0')
93
' pending@pending-0-0\n',
99
'P pending@pending-0-0\n',
103
def test_branch_status_revisions(self):
104
"""Tests branch status with revisions"""
105
wt = self.make_branch_and_tree('.')
107
self.build_tree(['hello.c', 'bye.c'])
110
wt.commit('Test message')
112
revs = [RevisionSpec.from_string('0')]
121
self.build_tree(['more.c'])
123
wt.commit('Another test message')
125
revs.append(RevisionSpec.from_string('1'))
134
def test_pending(self):
135
"""Pending merges display works, including Unicode"""
137
wt = self.make_branch_and_tree('branch')
139
wt.commit("Empty commit 1")
140
b_2_dir = b.bzrdir.sprout('./copy')
141
b_2 = b_2_dir.open_branch()
142
wt2 = b_2_dir.open_workingtree()
143
wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
144
merge(["./branch", -1], [None, None], this_dir = './copy')
145
message = self.status_string(wt2)
146
self.assertStartsWith(message, "pending merges:\n")
147
self.assertEndsWith(message, "Empty commit 2\n")
149
# must be long to make sure we see elipsis at the end
150
wt.commit("Empty commit 3 " +
151
"blah blah blah blah " * 100)
152
merge(["./branch", -1], [None, None], this_dir = './copy')
153
message = self.status_string(wt2)
154
self.assertStartsWith(message, "pending merges:\n")
155
self.assert_("Empty commit 3" in message)
156
self.assertEndsWith(message, "...\n")
158
def test_tree_status_ignores(self):
159
"""Tests branch status with ignores"""
160
wt = self.make_branch_and_tree('.')
161
self.run_bzr('ignore', '*~')
162
wt.commit('commit .bzrignore')
163
self.build_tree(['foo.c', 'foo.c~'])
174
def test_tree_status_specific_files(self):
175
"""Tests branch status with given specific files"""
176
wt = self.make_branch_and_tree('.')
179
self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
188
' directory/hello.c\n'
195
'? directory/hello.c\n'
200
self.assertRaises(errors.PathsDoNotExist,
202
wt, specific_files=['bye.c','test.c','absent.c'],
206
show_tree_status(wt, specific_files=['directory'], to_file=tof)
208
self.assertEquals(tof.readlines(),
210
' directory/hello.c\n'
213
show_tree_status(wt, specific_files=['directory'], to_file=tof,
216
self.assertEquals(tof.readlines(), ['? directory/hello.c\n'])
219
show_tree_status(wt, specific_files=['dir2'], to_file=tof)
221
self.assertEquals(tof.readlines(),
226
show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
228
self.assertEquals(tof.readlines(), ['? dir2/\n'])
230
def test_status_nonexistent_file(self):
231
# files that don't exist in either the basis tree or working tree
232
# should give an error
233
wt = self.make_branch_and_tree('.')
234
out, err = self.run_bzr('status', 'does-not-exist', retcode=3)
235
self.assertContainsRe(err, r'do not exist.*does-not-exist')
237
def test_status_out_of_date(self):
238
"""Simulate status of out-of-date tree after remote push"""
239
tree = self.make_branch_and_tree('.')
240
self.build_tree_contents([('a', 'foo\n')])
244
tree.commit('add test file')
245
# simulate what happens after a remote push
246
tree.set_last_revision("0")
247
out, err = self.run_bzr('status')
248
self.assertEqual("working tree is out of date, run 'bzr update'\n",
254
class CheckoutStatus(BranchStatus):
257
super(CheckoutStatus, self).setUp()
261
def make_branch_and_tree(self, relpath):
262
source = self.make_branch(pathjoin('..', relpath))
263
checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
264
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
265
return checkout.create_workingtree()
268
class TestStatus(TestCaseWithTransport):
270
def test_status(self):
273
self.build_tree(['hello.txt'])
274
result = self.run_bzr("status")[0]
275
self.assert_("unknown:\n hello.txt\n" in result, result)
276
result = self.run_bzr("status","--short")[0]
277
self.assertContainsRe(result, "[?] hello.txt\n")
279
self.run_bzr("add", "hello.txt")
280
result = self.run_bzr("status")[0]
281
self.assertContainsRe(result, "added:\n hello.txt\n")
282
result = self.run_bzr("status","--short")[0]
283
self.assertContainsRe(result, "[+]N hello.txt\n")
285
self.run_bzr("commit", "-m", "added")
286
result = self.run_bzr("status", "-r", "0..1")[0]
287
self.assertContainsRe(result, "added:\n hello.txt\n")
288
result = self.run_bzr("status", "--short", "-r", "0..1")[0]
289
self.assertContainsRe(result, "[+]N hello.txt\n")
291
self.build_tree(['world.txt'])
292
result = self.run_bzr("status", "-r", "0")[0]
293
self.assertContainsRe(result, "added:\n hello.txt\n" \
294
"unknown:\n world.txt\n")
295
result2 = self.run_bzr("status", "-r", "0..")[0]
296
self.assertEquals(result2, result)
297
result = self.run_bzr("status", "--short", "-r", "0")[0]
298
self.assertContainsRe(result, "[+]N hello.txt\n" \
300
result2 = self.run_bzr("status", "--short", "-r", "0..")[0]
301
self.assertEquals(result2, result)
303
def assertStatusContains(self, pattern):
304
"""Run status, and assert it contains the given pattern"""
305
result = self.run_bzr("status", "--short")[0]
306
self.assertContainsRe(result, pattern)
308
def test_kind_change_short(self):
309
tree = self.make_branch_and_tree('.')
310
self.build_tree(['file'])
312
tree.commit('added file')
314
self.build_tree(['file/'])
315
self.assertStatusContains('K file => file/')
316
tree.rename_one('file', 'directory')
317
self.assertStatusContains('RK file => directory/')
319
self.assertStatusContains('RD file => directory')
322
class TestStatusEncodings(TestCaseWithTransport):
325
TestCaseWithTransport.setUp(self)
326
self.user_encoding = bzrlib.user_encoding
327
self.stdout = sys.stdout
330
bzrlib.user_encoding = self.user_encoding
331
sys.stdout = self.stdout
332
TestCaseWithTransport.tearDown(self)
334
def make_uncommitted_tree(self):
335
"""Build a branch with uncommitted unicode named changes in the cwd."""
336
working_tree = self.make_branch_and_tree(u'.')
337
filename = u'hell\u00d8'
339
self.build_tree_contents([(filename, 'contents of hello')])
340
except UnicodeEncodeError:
341
raise TestSkipped("can't build unicode working tree in "
342
"filesystem encoding %s" % sys.getfilesystemencoding())
343
working_tree.add(filename)
346
def test_stdout_ascii(self):
347
sys.stdout = StringIO()
348
bzrlib.user_encoding = 'ascii'
349
working_tree = self.make_uncommitted_tree()
350
stdout, stderr = self.run_bzr("status")
352
self.assertEquals(stdout, """\
357
def test_stdout_latin1(self):
358
sys.stdout = StringIO()
359
bzrlib.user_encoding = 'latin-1'
360
working_tree = self.make_uncommitted_tree()
361
stdout, stderr = self.run_bzr('status')
363
self.assertEquals(stdout, u"""\
366
""".encode('latin-1'))