~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_status.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-03-01 03:31:37 UTC
  • mfrom: (2294.3.3 bzr.ab.integration)
  • Revision ID: pqm@pqm.ubuntu.com-20070301033137-9b87fdf211dc2e15
Fix #85305 by issuing an exception instead of a traceback.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#
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.
7
 
 
 
7
#
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.
12
 
 
 
12
#
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
16
16
 
17
 
 
18
17
"""Tests of status command.
19
18
 
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.
21
23
"""
22
24
 
23
 
 
24
 
from bzrlib.selftest import InTempDir
25
 
 
26
 
class BranchStatus(InTempDir):
27
 
    def runTest(self): 
28
 
        """Basic 'bzr mkdir' operation"""
29
 
        from cStringIO import StringIO
30
 
        from bzrlib.status import show_status
31
 
        from bzrlib.branch import Branch
32
 
        
33
 
        b = Branch('.', init=True)
34
 
 
35
 
        # status with nothing
36
 
        tof = StringIO()
37
 
        show_status(b, to_file=tof)
38
 
        self.assertEquals(tof.getvalue(), "")
39
 
 
40
 
        tof = StringIO()
41
 
        self.build_tree(['hello.c', 'bye.c'])
42
 
        show_status(b, to_file=tof)
43
 
        tof.seek(0)
44
 
        self.assertEquals(tof.readlines(),
45
 
                          ['unknown:\n',
46
 
                           '  bye.c\n',
47
 
                           '  hello.c\n',
48
 
                           ])
 
25
from cStringIO import StringIO
 
26
import codecs
 
27
from os import mkdir, chdir, rmdir, unlink
 
28
import sys
 
29
from tempfile import TemporaryFile
 
30
 
 
31
from bzrlib import bzrdir, errors
 
32
import bzrlib.branch
 
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
 
39
 
 
40
 
 
41
class BranchStatus(TestCaseWithTransport):
 
42
    
 
43
    def assertStatus(self, output_lines, working_tree,
 
44
        revision=None, short=False):
 
45
        """Run status in working_tree and look for output.
 
46
        
 
47
        :param output_lines: The lines to look for.
 
48
        :param working_tree: The tree to run status in.
 
49
        """
 
50
        output_string = self.status_string(working_tree, revision, short)
 
51
        self.assertEqual(output_lines, output_string.splitlines(True))
 
52
    
 
53
    def status_string(self, wt, revision=None, short=False):
 
54
        # use a real file rather than StringIO because it doesn't handle
 
55
        # Unicode very well.
 
56
        tof = codecs.getwriter('utf-8')(TemporaryFile())
 
57
        show_tree_status(wt, to_file=tof, revision=revision, short=short)
 
58
        tof.seek(0)
 
59
        return tof.read().decode('utf-8')
 
60
 
 
61
    def test_branch_status(self):
 
62
        """Test basic branch status"""
 
63
        wt = self.make_branch_and_tree('.')
 
64
 
 
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
 
68
        # as a corner case.
 
69
        self.assertStatus([], wt)
 
70
 
 
71
        self.build_tree(['hello.c', 'bye.c'])
 
72
        self.assertStatus([
 
73
                'unknown:\n',
 
74
                '  bye.c\n',
 
75
                '  hello.c\n',
 
76
            ],
 
77
            wt)
 
78
        self.assertStatus([
 
79
                '?   bye.c\n',
 
80
                '?   hello.c\n',
 
81
            ],
 
82
            wt, short=True)
 
83
 
 
84
        # add a commit to allow showing pending merges.
 
85
        wt.commit('create a parent to allow testing merge output')
 
86
 
 
87
        wt.add_parent_tree_id('pending@pending-0-0')
 
88
        self.assertStatus([
 
89
                'unknown:\n',
 
90
                '  bye.c\n',
 
91
                '  hello.c\n',
 
92
                'pending merges:\n',
 
93
                '  pending@pending-0-0\n',
 
94
            ],
 
95
            wt)
 
96
        self.assertStatus([
 
97
                '?   bye.c\n',
 
98
                '?   hello.c\n',
 
99
                'P   pending@pending-0-0\n',
 
100
            ],
 
101
            wt, short=True)
 
102
 
 
103
    def test_branch_status_revisions(self):
 
104
        """Tests branch status with revisions"""
 
105
        wt = self.make_branch_and_tree('.')
 
106
 
 
107
        self.build_tree(['hello.c', 'bye.c'])
 
108
        wt.add('hello.c')
 
109
        wt.add('bye.c')
 
110
        wt.commit('Test message')
 
111
 
 
112
        revs = [RevisionSpec.from_string('0')]
 
113
        self.assertStatus([
 
114
                'added:\n',
 
115
                '  bye.c\n',
 
116
                '  hello.c\n'
 
117
            ],
 
118
            wt,
 
119
            revision=revs)
 
120
 
 
121
        self.build_tree(['more.c'])
 
122
        wt.add('more.c')
 
123
        wt.commit('Another test message')
 
124
        
 
125
        revs.append(RevisionSpec.from_string('1'))
 
126
        self.assertStatus([
 
127
                'added:\n',
 
128
                '  bye.c\n',
 
129
                '  hello.c\n',
 
130
            ],
 
131
            wt,
 
132
            revision=revs)
 
133
 
 
134
    def test_pending(self):
 
135
        """Pending merges display works, including Unicode"""
 
136
        mkdir("./branch")
 
137
        wt = self.make_branch_and_tree('branch')
 
138
        b = wt.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")
 
148
        wt2.commit("merged")
 
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")
 
157
 
 
158
    def test_branch_status_specific_files(self): 
 
159
        """Tests branch status with given specific files"""
 
160
        wt = self.make_branch_and_tree('.')
 
161
        b = wt.branch
 
162
 
 
163
        self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
 
164
        wt.add('directory')
 
165
        wt.add('test.c')
 
166
        wt.commit('testing')
 
167
        
 
168
        self.assertStatus([
 
169
                'unknown:\n',
 
170
                '  bye.c\n',
 
171
                '  dir2\n',
 
172
                '  directory/hello.c\n'
 
173
                ],
 
174
                wt)
 
175
 
 
176
        self.assertStatus([
 
177
                '?   bye.c\n',
 
178
                '?   dir2\n',
 
179
                '?   directory/hello.c\n'
 
180
                ],
 
181
                wt, short=True)
 
182
 
 
183
        tof = StringIO()
 
184
        self.assertRaises(errors.PathsDoNotExist,
 
185
                          show_tree_status,
 
186
                          wt, specific_files=['bye.c','test.c','absent.c'], 
 
187
                          to_file=tof)
 
188
        
 
189
        tof = StringIO()
 
190
        show_tree_status(wt, specific_files=['directory'], to_file=tof)
 
191
        tof.seek(0)
 
192
        self.assertEquals(tof.readlines(),
 
193
                          ['unknown:\n',
 
194
                           '  directory/hello.c\n'
 
195
                           ])
 
196
        tof = StringIO()
 
197
        show_tree_status(wt, specific_files=['directory'], to_file=tof,
 
198
                         short=True)
 
199
        tof.seek(0)
 
200
        self.assertEquals(tof.readlines(), ['?   directory/hello.c\n'])
 
201
 
 
202
        tof = StringIO()
 
203
        show_tree_status(wt, specific_files=['dir2'], to_file=tof)
 
204
        tof.seek(0)
 
205
        self.assertEquals(tof.readlines(),
 
206
                          ['unknown:\n',
 
207
                           '  dir2\n'
 
208
                           ])
 
209
        tof = StringIO()
 
210
        show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
 
211
        tof.seek(0)
 
212
        self.assertEquals(tof.readlines(), ['?   dir2\n'])
 
213
 
 
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')
 
220
 
 
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')])
 
225
        tree.lock_write()
 
226
        try:
 
227
            tree.add(['a'])
 
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",
 
233
                             err)
 
234
        finally:
 
235
            tree.unlock()
 
236
 
 
237
 
 
238
class CheckoutStatus(BranchStatus):
 
239
 
 
240
    def setUp(self):
 
241
        super(CheckoutStatus, self).setUp()
 
242
        mkdir('codir')
 
243
        chdir('codir')
 
244
        
 
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()
 
250
 
 
251
 
 
252
class TestStatus(TestCaseWithTransport):
 
253
 
 
254
    def test_status(self):
 
255
        self.run_bzr("init")
 
256
 
 
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")
 
262
 
 
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")
 
268
 
 
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")
 
274
 
 
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" \
 
283
                                      "[?]   world.txt\n")
 
284
        result2 = self.run_bzr("status", "--short", "-r", "0..")[0]
 
285
        self.assertEquals(result2, result)
 
286
 
 
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)
 
291
 
 
292
    def test_kind_change_short(self):
 
293
        tree = self.make_branch_and_tree('.')
 
294
        self.build_tree(['file'])
 
295
        tree.add('file')
 
296
        tree.commit('added file')
 
297
        unlink('file')
 
298
        self.build_tree(['file/'])
 
299
        self.assertStatusContains('K  file => file/')
 
300
        tree.rename_one('file', 'directory')
 
301
        self.assertStatusContains('RK  file => directory/')
 
302
        rmdir('directory')
 
303
        self.assertStatusContains('RD  file => directory')
 
304
 
 
305
 
 
306
class TestStatusEncodings(TestCaseWithTransport):
 
307
    
 
308
    def setUp(self):
 
309
        TestCaseWithTransport.setUp(self)
 
310
        self.user_encoding = bzrlib.user_encoding
 
311
        self.stdout = sys.stdout
 
312
 
 
313
    def tearDown(self):
 
314
        bzrlib.user_encoding = self.user_encoding
 
315
        sys.stdout = self.stdout
 
316
        TestCaseWithTransport.tearDown(self)
 
317
 
 
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'
 
322
        try:
 
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)
 
328
        return working_tree
 
329
 
 
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")
 
335
 
 
336
        self.assertEquals(stdout, """\
 
337
added:
 
338
  hell?
 
339
""")
 
340
 
 
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')
 
346
 
 
347
        self.assertEquals(stdout, u"""\
 
348
added:
 
349
  hell\u00d8
 
350
""".encode('latin-1'))
49
351