1
# Copyright (C) 2005 by Canonical Ltd
1
# Copyright (C) 2005, 2006 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
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
25
from cStringIO import StringIO
27
from os import mkdir, chdir
26
29
from tempfile import TemporaryFile
29
from bzrlib.tests import TestCaseInTempDir
31
from bzrlib import bzrdir, errors, ignores
33
from bzrlib.builtins import merge
34
from bzrlib.osutils import pathjoin
30
35
from bzrlib.revisionspec import RevisionSpec
31
from bzrlib.merge import merge
32
from bzrlib.status import show_status
33
from bzrlib.branch import Branch
34
from bzrlib.clone import copy_branch
36
class BranchStatus(TestCaseInTempDir):
38
def test_branch_status(self):
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,
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)
51
self.assertEqual(output_lines, output_string.splitlines(True))
53
def status_string(self, wt, revision=None):
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)
59
return tof.read().decode('utf-8')
61
def test_branch_status(self):
39
62
"""Test basic branch status"""
40
from bzrlib.status import show_status
41
from bzrlib.branch import Branch
43
b = Branch.initialize(u'.')
47
show_status(b, to_file=tof)
48
self.assertEquals(tof.getvalue(), "")
63
wt = self.make_branch_and_tree('.')
65
ignores._set_user_ignores(['./.bazaar'])
67
# status with no commits or files - it must
68
# work and show no output. We do this with no
69
# commits to be sure that it's not going to fail
71
self.assertStatus([], wt)
51
73
self.build_tree(['hello.c', 'bye.c'])
52
b.working_tree().add_pending_merge('pending@pending-0-0')
53
show_status(b, to_file=tof)
55
self.assertEquals(tof.readlines(),
60
' pending@pending-0-0\n'
81
# add a commit to allow showing pending merges.
82
wt.commit('create a parent to allow testing merge output')
84
wt.add_parent_tree_id('pending@pending-0-0')
90
' pending@pending-0-0\n',
63
94
def test_branch_status_revisions(self):
64
95
"""Tests branch status with revisions"""
66
b = Branch.initialize(u'.')
96
wt = self.make_branch_and_tree('.')
98
ignores._set_user_ignores(['./.bazaar'])
69
100
self.build_tree(['hello.c', 'bye.c'])
70
b.working_tree().add('hello.c')
71
b.working_tree().add('bye.c')
72
b.working_tree().commit('Test message')
103
wt.commit('Test message')
76
revs.append(RevisionSpec(0))
78
show_status(b, to_file=tof, revision=revs)
81
self.assertEquals(tof.readlines(),
105
revs = [RevisionSpec(0)]
86
114
self.build_tree(['more.c'])
87
b.working_tree().add('more.c')
88
b.working_tree().commit('Another test message')
116
wt.commit('Another test message')
91
118
revs.append(RevisionSpec(1))
93
show_status(b, to_file=tof, revision=revs)
96
self.assertEquals(tof.readlines(),
101
def status_string(self, branch):
102
# use a real file rather than StringIO because it doesn't handle
104
tof = codecs.getwriter('utf-8')(TemporaryFile())
105
show_status(branch, to_file=tof)
107
return tof.read().decode('utf-8')
109
127
def test_pending(self):
110
128
"""Pending merges display works, including Unicode"""
111
129
mkdir("./branch")
112
b = Branch.initialize('./branch')
113
b.working_tree().commit("Empty commit 1")
114
b_2 = copy_branch(b, './copy')
115
b.working_tree().commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
130
wt = self.make_branch_and_tree('branch')
132
wt.commit("Empty commit 1")
133
b_2_dir = b.bzrdir.sprout('./copy')
134
b_2 = b_2_dir.open_branch()
135
wt2 = b_2_dir.open_workingtree()
136
wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
116
137
merge(["./branch", -1], [None, None], this_dir = './copy')
117
message = self.status_string(b_2)
138
message = self.status_string(wt2)
118
139
self.assert_(message.startswith("pending merges:\n"))
119
140
self.assert_(message.endswith("Empty commit 2\n"))
120
b_2.working_tree().commit("merged")
121
142
# must be long to make sure we see elipsis at the end
122
b.working_tree().commit("Empty commit 3 " +
123
"blah blah blah blah " * 10)
143
wt.commit("Empty commit 3 " +
144
"blah blah blah blah " * 10)
124
145
merge(["./branch", -1], [None, None], this_dir = './copy')
125
message = self.status_string(b_2)
146
message = self.status_string(wt2)
126
147
self.assert_(message.startswith("pending merges:\n"))
127
148
self.assert_("Empty commit 3" in message)
128
149
self.assert_(message.endswith("...\n"))
130
151
def test_branch_status_specific_files(self):
131
152
"""Tests branch status with given specific files"""
132
from cStringIO import StringIO
133
from bzrlib.status import show_status
134
from bzrlib.branch import Branch
136
b = Branch.initialize(u'.')
153
wt = self.make_branch_and_tree('.')
156
ignores._set_user_ignores(['./.bazaar'])
138
158
self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
139
b.working_tree().add('directory')
140
b.working_tree().add('test.c')
141
b.working_tree().commit('testing')
144
show_status(b, to_file=tof)
164
show_tree_status(wt, to_file=tof)
146
166
self.assertEquals(tof.readlines(),
150
170
' directory/hello.c\n'
154
show_status(b, specific_files=['bye.c','test.c','absent.c'], to_file=tof)
156
self.assertEquals(tof.readlines(),
173
self.assertRaises(errors.PathsDoNotExist,
175
wt, specific_files=['bye.c','test.c','absent.c'],
162
show_status(b, specific_files=['directory'], to_file=tof)
179
show_tree_status(wt, specific_files=['directory'], to_file=tof)
164
181
self.assertEquals(tof.readlines(),
166
183
' directory/hello.c\n'
169
show_status(b, specific_files=['dir2'], to_file=tof)
186
show_tree_status(wt, specific_files=['dir2'], to_file=tof)
171
188
self.assertEquals(tof.readlines(),
193
def test_status_nonexistent_file(self):
194
# files that don't exist in either the basis tree or working tree
195
# should give an error
196
wt = self.make_branch_and_tree('.')
197
out, err = self.run_bzr('status', 'does-not-exist', retcode=3)
198
self.assertContainsRe(err, r'do not exist.*does-not-exist')
201
class CheckoutStatus(BranchStatus):
204
super(CheckoutStatus, self).setUp()
208
def make_branch_and_tree(self, relpath):
209
source = self.make_branch(pathjoin('..', relpath))
210
checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
211
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
212
return checkout.create_workingtree()
215
class TestStatus(TestCaseWithTransport):
217
def test_status(self):
218
ignores._set_user_ignores(['./.bazaar'])
221
self.build_tree(['hello.txt'])
222
result = self.run_bzr("status")[0]
223
self.assert_("unknown:\n hello.txt\n" in result, result)
224
self.run_bzr("add", "hello.txt")
225
result = self.run_bzr("status")[0]
226
self.assert_("added:\n hello.txt\n" in result, result)
227
self.run_bzr("commit", "-m", "added")
228
result = self.run_bzr("status", "-r", "0..1")[0]
229
self.assert_("added:\n hello.txt\n" in result, result)
230
self.build_tree(['world.txt'])
231
result = self.run_bzr("status", "-r", "0")[0]
232
self.assert_("added:\n hello.txt\n" \
233
"unknown:\n world.txt\n" in result, result)
235
result2 = self.run_bzr("status", "-r", "0..")[0]
236
self.assertEquals(result2, result)
239
class TestStatusEncodings(TestCaseWithTransport):
242
TestCaseWithTransport.setUp(self)
243
self.user_encoding = bzrlib.user_encoding
244
self.stdout = sys.stdout
247
bzrlib.user_encoding = self.user_encoding
248
sys.stdout = self.stdout
249
TestCaseWithTransport.tearDown(self)
251
def make_uncommitted_tree(self):
252
"""Build a branch with uncommitted unicode named changes in the cwd."""
253
working_tree = self.make_branch_and_tree(u'.')
254
filename = u'hell\u00d8'
256
self.build_tree_contents([(filename, 'contents of hello')])
257
except UnicodeEncodeError:
258
raise TestSkipped("can't build unicode working tree in "
259
"filesystem encoding %s" % sys.getfilesystemencoding())
260
working_tree.add(filename)
263
def test_stdout_ascii(self):
264
sys.stdout = StringIO()
265
bzrlib.user_encoding = 'ascii'
266
working_tree = self.make_uncommitted_tree()
267
stdout, stderr = self.run_bzr("status")
269
self.assertEquals(stdout, """\
274
def test_stdout_latin1(self):
275
sys.stdout = StringIO()
276
bzrlib.user_encoding = 'latin-1'
277
working_tree = self.make_uncommitted_tree()
278
stdout, stderr = self.run_bzr('status')
280
self.assertEquals(stdout, u"""\
283
""".encode('latin-1'))