~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-12 16:31:21 UTC
  • mfrom: (2329.1.2 knit_corrupt)
  • Revision ID: pqm@pqm.ubuntu.com-20070312163121-a8078e3704c91ffe
(John Arbash Meinel) raise more helpful errors when detecting Knit corruption.

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, expected_lines, working_tree,
 
44
        revision=None, short=False):
 
45
        """Run status in working_tree and look for output.
 
46
        
 
47
        :param expected_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(expected_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_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~'])
 
164
        self.assertStatus([
 
165
                'unknown:\n',
 
166
                '  foo.c\n',
 
167
                ],
 
168
                wt)
 
169
        self.assertStatus([
 
170
                '?   foo.c\n',
 
171
                ],
 
172
                wt, short=True)
 
173
 
 
174
    def test_tree_status_specific_files(self):
 
175
        """Tests branch status with given specific files"""
 
176
        wt = self.make_branch_and_tree('.')
 
177
        b = wt.branch
 
178
 
 
179
        self.build_tree(['directory/','directory/hello.c', 'bye.c','test.c','dir2/'])
 
180
        wt.add('directory')
 
181
        wt.add('test.c')
 
182
        wt.commit('testing')
 
183
        
 
184
        self.assertStatus([
 
185
                'unknown:\n',
 
186
                '  bye.c\n',
 
187
                '  dir2/\n',
 
188
                '  directory/hello.c\n'
 
189
                ],
 
190
                wt)
 
191
 
 
192
        self.assertStatus([
 
193
                '?   bye.c\n',
 
194
                '?   dir2/\n',
 
195
                '?   directory/hello.c\n'
 
196
                ],
 
197
                wt, short=True)
 
198
 
 
199
        tof = StringIO()
 
200
        self.assertRaises(errors.PathsDoNotExist,
 
201
                          show_tree_status,
 
202
                          wt, specific_files=['bye.c','test.c','absent.c'], 
 
203
                          to_file=tof)
 
204
        
 
205
        tof = StringIO()
 
206
        show_tree_status(wt, specific_files=['directory'], to_file=tof)
 
207
        tof.seek(0)
 
208
        self.assertEquals(tof.readlines(),
 
209
                          ['unknown:\n',
 
210
                           '  directory/hello.c\n'
 
211
                           ])
 
212
        tof = StringIO()
 
213
        show_tree_status(wt, specific_files=['directory'], to_file=tof,
 
214
                         short=True)
 
215
        tof.seek(0)
 
216
        self.assertEquals(tof.readlines(), ['?   directory/hello.c\n'])
 
217
 
 
218
        tof = StringIO()
 
219
        show_tree_status(wt, specific_files=['dir2'], to_file=tof)
 
220
        tof.seek(0)
 
221
        self.assertEquals(tof.readlines(),
 
222
                          ['unknown:\n',
 
223
                           '  dir2/\n'
 
224
                           ])
 
225
        tof = StringIO()
 
226
        show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
 
227
        tof.seek(0)
 
228
        self.assertEquals(tof.readlines(), ['?   dir2/\n'])
 
229
 
 
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')
 
236
 
 
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')])
 
241
        tree.lock_write()
 
242
        try:
 
243
            tree.add(['a'])
 
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",
 
249
                             err)
 
250
        finally:
 
251
            tree.unlock()
 
252
 
 
253
 
 
254
class CheckoutStatus(BranchStatus):
 
255
 
 
256
    def setUp(self):
 
257
        super(CheckoutStatus, self).setUp()
 
258
        mkdir('codir')
 
259
        chdir('codir')
 
260
        
 
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()
 
266
 
 
267
 
 
268
class TestStatus(TestCaseWithTransport):
 
269
 
 
270
    def test_status(self):
 
271
        self.run_bzr("init")
 
272
 
 
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")
 
278
 
 
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")
 
284
 
 
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")
 
290
 
 
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" \
 
299
                                      "[?]   world.txt\n")
 
300
        result2 = self.run_bzr("status", "--short", "-r", "0..")[0]
 
301
        self.assertEquals(result2, result)
 
302
 
 
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)
 
307
 
 
308
    def test_kind_change_short(self):
 
309
        tree = self.make_branch_and_tree('.')
 
310
        self.build_tree(['file'])
 
311
        tree.add('file')
 
312
        tree.commit('added file')
 
313
        unlink('file')
 
314
        self.build_tree(['file/'])
 
315
        self.assertStatusContains('K  file => file/')
 
316
        tree.rename_one('file', 'directory')
 
317
        self.assertStatusContains('RK  file => directory/')
 
318
        rmdir('directory')
 
319
        self.assertStatusContains('RD  file => directory')
 
320
 
 
321
 
 
322
class TestStatusEncodings(TestCaseWithTransport):
 
323
    
 
324
    def setUp(self):
 
325
        TestCaseWithTransport.setUp(self)
 
326
        self.user_encoding = bzrlib.user_encoding
 
327
        self.stdout = sys.stdout
 
328
 
 
329
    def tearDown(self):
 
330
        bzrlib.user_encoding = self.user_encoding
 
331
        sys.stdout = self.stdout
 
332
        TestCaseWithTransport.tearDown(self)
 
333
 
 
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'
 
338
        try:
 
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)
 
344
        return working_tree
 
345
 
 
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")
 
351
 
 
352
        self.assertEquals(stdout, """\
 
353
added:
 
354
  hell?
 
355
""")
 
356
 
 
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')
 
362
 
 
363
        self.assertEquals(stdout, u"""\
 
364
added:
 
365
  hell\u00d8
 
366
""".encode('latin-1'))
49
367