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.
24
from bzrlib.selftest import TestCaseInTempDir
25
from bzrlib.revisionspec import RevisionSpec
26
from bzrlib.merge import merge
25
27
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, output_lines, working_tree,
44
revision=None, short=False):
45
"""Run status in working_tree and look for output.
47
:param output_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(output_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):
28
from bzrlib.status import show_status
29
from bzrlib.branch import Branch
31
from bzrlib.clone import copy_branch
33
class BranchStatus(TestCaseInTempDir):
35
def test_branch_status(self):
62
36
"""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)
37
from cStringIO import StringIO
38
from bzrlib.status import show_status
39
from bzrlib.branch import Branch
41
b = Branch.initialize('.')
45
show_status(b, to_file=tof)
46
self.assertEquals(tof.getvalue(), "")
71
49
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',
50
b.add_pending_merge('pending@pending-0-0')
51
show_status(b, to_file=tof)
53
self.assertEquals(tof.readlines(),
58
' pending@pending-0-0\n'
103
61
def test_branch_status_revisions(self):
104
62
"""Tests branch status with revisions"""
105
wt = self.make_branch_and_tree('.')
64
b = Branch.initialize('.')
107
67
self.build_tree(['hello.c', 'bye.c'])
110
wt.commit('Test message')
70
b.commit('Test message')
112
revs = [RevisionSpec.from_string('0')]
74
revs.append(RevisionSpec(0))
76
show_status(b, to_file=tof, revision=revs)
79
self.assertEquals(tof.readlines(),
121
84
self.build_tree(['more.c'])
123
wt.commit('Another test message')
125
revs.append(RevisionSpec.from_string('1'))
86
b.commit('Another test message')
89
revs.append(RevisionSpec(1))
91
show_status(b, to_file=tof, revision=revs)
94
self.assertEquals(tof.readlines(),
99
def status_string(self, branch):
101
show_status(branch, to_file=tof)
103
return tof.getvalue()
134
105
def test_pending(self):
135
"""Pending merges display works, including Unicode"""
106
"""Pending merges display works"""
136
107
mkdir("./branch")
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")
108
b = Branch.initialize('./branch')
109
b.commit("Empty commit 1")
110
b_2 = copy_branch(b, './copy')
111
b.commit("Empty commit 2")
144
112
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")
113
message = self.status_string(b_2)
114
assert (message.startswith("pending merges:\n")), message
115
assert (message.endswith("Empty commit 2\n")), message
149
117
# must be long to make sure we see elipsis at the end
150
wt.commit("Empty commit 3 " +
151
"blah blah blah blah " * 100)
118
b.commit("Empty commit 3 blah blah blah blah blah blah blah blah blah"
119
" blah blah blah blah blah blah bleh")
152
120
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")
121
message = self.status_string(b_2)
122
assert (message.startswith("pending merges:\n")), message
123
assert ("Empty commit 3" in message), message
124
assert (message.endswith("...\n")), message
158
126
def test_branch_status_specific_files(self):
159
127
"""Tests branch status with given specific files"""
160
wt = self.make_branch_and_tree('.')
128
from cStringIO import StringIO
129
from bzrlib.status import show_status
130
from bzrlib.branch import Branch
132
b = Branch.initialize('.')
163
134
self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
172
' directory/hello.c\n'
179
'? directory/hello.c\n'
184
self.assertRaises(errors.PathsDoNotExist,
186
wt, specific_files=['bye.c','test.c','absent.c'],
190
show_tree_status(wt, specific_files=['directory'], to_file=tof)
192
self.assertEquals(tof.readlines(),
194
' directory/hello.c\n'
197
show_tree_status(wt, specific_files=['directory'], to_file=tof,
200
self.assertEquals(tof.readlines(), ['? directory/hello.c\n'])
203
show_tree_status(wt, specific_files=['dir2'], to_file=tof)
140
show_status(b, to_file=tof)
142
self.assertEquals(tof.readlines(),
146
' directory/hello.c\n'
150
show_status(b, specific_files=['bye.c','test.c','absent.c'], to_file=tof)
152
self.assertEquals(tof.readlines(),
158
show_status(b, specific_files=['directory'], to_file=tof)
160
self.assertEquals(tof.readlines(),
162
' directory/hello.c\n'
165
show_status(b, specific_files=['dir2'], to_file=tof)
205
167
self.assertEquals(tof.readlines(),
210
show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
212
self.assertEquals(tof.readlines(), ['? dir2\n'])
214
def test_status_nonexistent_file(self):
215
# files that don't exist in either the basis tree or working tree
216
# should give an error
217
wt = self.make_branch_and_tree('.')
218
out, err = self.run_bzr('status', 'does-not-exist', retcode=3)
219
self.assertContainsRe(err, r'do not exist.*does-not-exist')
221
def test_status_out_of_date(self):
222
"""Simulate status of out-of-date tree after remote push"""
223
tree = self.make_branch_and_tree('.')
224
self.build_tree_contents([('a', 'foo\n')])
228
tree.commit('add test file')
229
# simulate what happens after a remote push
230
tree.set_last_revision("0")
231
out, err = self.run_bzr('status')
232
self.assertEqual("working tree is out of date, run 'bzr update'\n",
238
class CheckoutStatus(BranchStatus):
241
super(CheckoutStatus, self).setUp()
245
def make_branch_and_tree(self, relpath):
246
source = self.make_branch(pathjoin('..', relpath))
247
checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
248
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
249
return checkout.create_workingtree()
252
class TestStatus(TestCaseWithTransport):
254
def test_status(self):
257
self.build_tree(['hello.txt'])
258
result = self.run_bzr("status")[0]
259
self.assert_("unknown:\n hello.txt\n" in result, result)
260
result = self.run_bzr("status","--short")[0]
261
self.assertContainsRe(result, "[?] hello.txt\n")
263
self.run_bzr("add", "hello.txt")
264
result = self.run_bzr("status")[0]
265
self.assertContainsRe(result, "added:\n hello.txt\n")
266
result = self.run_bzr("status","--short")[0]
267
self.assertContainsRe(result, "[+]N hello.txt\n")
269
self.run_bzr("commit", "-m", "added")
270
result = self.run_bzr("status", "-r", "0..1")[0]
271
self.assertContainsRe(result, "added:\n hello.txt\n")
272
result = self.run_bzr("status", "--short", "-r", "0..1")[0]
273
self.assertContainsRe(result, "[+]N hello.txt\n")
275
self.build_tree(['world.txt'])
276
result = self.run_bzr("status", "-r", "0")[0]
277
self.assertContainsRe(result, "added:\n hello.txt\n" \
278
"unknown:\n world.txt\n")
279
result2 = self.run_bzr("status", "-r", "0..")[0]
280
self.assertEquals(result2, result)
281
result = self.run_bzr("status", "--short", "-r", "0")[0]
282
self.assertContainsRe(result, "[+]N hello.txt\n" \
284
result2 = self.run_bzr("status", "--short", "-r", "0..")[0]
285
self.assertEquals(result2, result)
287
def assertStatusContains(self, pattern):
288
"""Run status, and assert it contains the given pattern"""
289
result = self.run_bzr("status", "--short")[0]
290
self.assertContainsRe(result, pattern)
292
def test_kind_change_short(self):
293
tree = self.make_branch_and_tree('.')
294
self.build_tree(['file'])
296
tree.commit('added file')
298
self.build_tree(['file/'])
299
self.assertStatusContains('K file => file/')
300
tree.rename_one('file', 'directory')
301
self.assertStatusContains('RK file => directory/')
303
self.assertStatusContains('RD file => directory')
306
class TestStatusEncodings(TestCaseWithTransport):
309
TestCaseWithTransport.setUp(self)
310
self.user_encoding = bzrlib.user_encoding
311
self.stdout = sys.stdout
314
bzrlib.user_encoding = self.user_encoding
315
sys.stdout = self.stdout
316
TestCaseWithTransport.tearDown(self)
318
def make_uncommitted_tree(self):
319
"""Build a branch with uncommitted unicode named changes in the cwd."""
320
working_tree = self.make_branch_and_tree(u'.')
321
filename = u'hell\u00d8'
323
self.build_tree_contents([(filename, 'contents of hello')])
324
except UnicodeEncodeError:
325
raise TestSkipped("can't build unicode working tree in "
326
"filesystem encoding %s" % sys.getfilesystemencoding())
327
working_tree.add(filename)
330
def test_stdout_ascii(self):
331
sys.stdout = StringIO()
332
bzrlib.user_encoding = 'ascii'
333
working_tree = self.make_uncommitted_tree()
334
stdout, stderr = self.run_bzr("status")
336
self.assertEquals(stdout, """\
341
def test_stdout_latin1(self):
342
sys.stdout = StringIO()
343
bzrlib.user_encoding = 'latin-1'
344
working_tree = self.make_uncommitted_tree()
345
stdout, stderr = self.run_bzr('status')
347
self.assertEquals(stdout, u"""\
350
""".encode('latin-1'))