~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Robert Collins
  • Date: 2007-03-08 04:06:06 UTC
  • mfrom: (2323.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 2442.
  • Revision ID: robertc@robertcollins.net-20070308040606-84gsniv56huiyjt4
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 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.
23
22
interface later, they will be non blackbox tests.
24
23
"""
25
24
 
26
 
 
27
25
from cStringIO import StringIO
28
 
from os import mkdir, chdir
 
26
import codecs
 
27
from os import mkdir, chdir, rmdir, unlink
 
28
import sys
29
29
from tempfile import TemporaryFile
30
 
import codecs
31
30
 
 
31
from bzrlib import bzrdir, errors
32
32
import bzrlib.branch
33
33
from bzrlib.builtins import merge
34
 
import bzrlib.bzrdir as bzrdir
35
 
import bzrlib.errors as errors
36
34
from bzrlib.osutils import pathjoin
37
35
from bzrlib.revisionspec import RevisionSpec
38
36
from bzrlib.status import show_tree_status
39
 
from bzrlib.tests import TestCaseWithTransport
 
37
from bzrlib.tests import TestCaseWithTransport, TestSkipped
40
38
from bzrlib.workingtree import WorkingTree
41
39
 
42
40
 
43
41
class BranchStatus(TestCaseWithTransport):
44
42
    
45
 
    def test_branch_status(self): 
 
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):
46
62
        """Test basic branch status"""
47
63
        wt = self.make_branch_and_tree('.')
48
 
        b = wt.branch
49
 
 
50
 
        # status with nothing
51
 
        tof = StringIO()
52
 
        show_tree_status(wt, to_file=tof)
53
 
        self.assertEquals(tof.getvalue(), "")
54
 
 
55
 
        tof = StringIO()
 
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
 
56
71
        self.build_tree(['hello.c', 'bye.c'])
57
 
        wt.add_pending_merge('pending@pending-0-0')
58
 
        show_tree_status(wt, to_file=tof)
59
 
        tof.seek(0)
60
 
        self.assertEquals(tof.readlines(),
61
 
                          ['unknown:\n',
62
 
                           '  bye.c\n',
63
 
                           '  hello.c\n',
64
 
                           'pending merges:\n',
65
 
                           '  pending@pending-0-0\n'
66
 
                           ])
 
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)
67
102
 
68
103
    def test_branch_status_revisions(self):
69
104
        """Tests branch status with revisions"""
70
105
        wt = self.make_branch_and_tree('.')
71
 
        b = wt.branch
72
106
 
73
 
        tof = StringIO()
74
107
        self.build_tree(['hello.c', 'bye.c'])
75
108
        wt.add('hello.c')
76
109
        wt.add('bye.c')
77
110
        wt.commit('Test message')
78
111
 
79
 
        tof = StringIO()
80
 
        revs =[]
81
 
        revs.append(RevisionSpec(0))
82
 
        
83
 
        show_tree_status(wt, to_file=tof, revision=revs)
84
 
        
85
 
        tof.seek(0)
86
 
        self.assertEquals(tof.readlines(),
87
 
                          ['added:\n',
88
 
                           '  bye.c\n',
89
 
                           '  hello.c\n'])
 
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)
90
120
 
91
121
        self.build_tree(['more.c'])
92
122
        wt.add('more.c')
93
123
        wt.commit('Another test message')
94
124
        
95
 
        tof = StringIO()
96
 
        revs.append(RevisionSpec(1))
97
 
        
98
 
        show_tree_status(wt, to_file=tof, revision=revs)
99
 
        
100
 
        tof.seek(0)
101
 
        self.assertEquals(tof.readlines(),
102
 
                          ['added:\n',
103
 
                           '  bye.c\n',
104
 
                           '  hello.c\n'])
105
 
 
106
 
    def status_string(self, wt):
107
 
        # use a real file rather than StringIO because it doesn't handle
108
 
        # Unicode very well.
109
 
        tof = codecs.getwriter('utf-8')(TemporaryFile())
110
 
        show_tree_status(wt, to_file=tof)
111
 
        tof.seek(0)
112
 
        return tof.read().decode('utf-8')
 
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)
113
133
 
114
134
    def test_pending(self):
115
135
        """Pending merges display works, including Unicode"""
123
143
        wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
124
144
        merge(["./branch", -1], [None, None], this_dir = './copy')
125
145
        message = self.status_string(wt2)
126
 
        self.assert_(message.startswith("pending merges:\n"))
127
 
        self.assert_(message.endswith("Empty commit 2\n")) 
 
146
        self.assertStartsWith(message, "pending merges:\n")
 
147
        self.assertEndsWith(message, "Empty commit 2\n")
128
148
        wt2.commit("merged")
129
149
        # must be long to make sure we see elipsis at the end
130
 
        wt.commit("Empty commit 3 " + 
131
 
                   "blah blah blah blah " * 10)
 
150
        wt.commit("Empty commit 3 " +
 
151
                   "blah blah blah blah " * 100)
132
152
        merge(["./branch", -1], [None, None], this_dir = './copy')
133
153
        message = self.status_string(wt2)
134
 
        self.assert_(message.startswith("pending merges:\n"))
 
154
        self.assertStartsWith(message, "pending merges:\n")
135
155
        self.assert_("Empty commit 3" in message)
136
 
        self.assert_(message.endswith("...\n")) 
137
 
 
138
 
    def test_branch_status_specific_files(self): 
 
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):
139
175
        """Tests branch status with given specific files"""
140
176
        wt = self.make_branch_and_tree('.')
141
177
        b = wt.branch
145
181
        wt.add('test.c')
146
182
        wt.commit('testing')
147
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
 
148
199
        tof = StringIO()
149
 
        show_tree_status(wt, to_file=tof)
150
 
        tof.seek(0)
151
 
        self.assertEquals(tof.readlines(),
152
 
                          ['unknown:\n',
153
 
                           '  bye.c\n',
154
 
                           '  dir2\n',
155
 
                           '  directory/hello.c\n'
156
 
                           ])
157
 
 
158
200
        self.assertRaises(errors.PathsDoNotExist,
159
201
                          show_tree_status,
160
202
                          wt, specific_files=['bye.c','test.c','absent.c'], 
168
210
                           '  directory/hello.c\n'
169
211
                           ])
170
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()
171
219
        show_tree_status(wt, specific_files=['dir2'], to_file=tof)
172
220
        tof.seek(0)
173
221
        self.assertEquals(tof.readlines(),
174
222
                          ['unknown:\n',
175
 
                           '  dir2\n'
 
223
                           '  dir2/\n'
176
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'])
177
229
 
178
230
    def test_status_nonexistent_file(self):
179
231
        # files that don't exist in either the basis tree or working tree
182
234
        out, err = self.run_bzr('status', 'does-not-exist', retcode=3)
183
235
        self.assertContainsRe(err, r'do not exist.*does-not-exist')
184
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
 
185
253
 
186
254
class CheckoutStatus(BranchStatus):
187
255
 
201
269
 
202
270
    def test_status(self):
203
271
        self.run_bzr("init")
 
272
 
204
273
        self.build_tree(['hello.txt'])
205
274
        result = self.run_bzr("status")[0]
206
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
 
207
279
        self.run_bzr("add", "hello.txt")
208
280
        result = self.run_bzr("status")[0]
209
 
        self.assert_("added:\n  hello.txt\n" in result, result)
 
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
 
210
285
        self.run_bzr("commit", "-m", "added")
211
286
        result = self.run_bzr("status", "-r", "0..1")[0]
212
 
        self.assert_("added:\n  hello.txt\n" in result, result)
 
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
 
213
291
        self.build_tree(['world.txt'])
214
292
        result = self.run_bzr("status", "-r", "0")[0]
215
 
        self.assert_("added:\n  hello.txt\n" \
216
 
                     "unknown:\n  world.txt\n" in result, result)
217
 
 
 
293
        self.assertContainsRe(result, "added:\n  hello.txt\n" \
 
294
                                      "unknown:\n  world.txt\n")
218
295
        result2 = self.run_bzr("status", "-r", "0..")[0]
219
296
        self.assertEquals(result2, result)
220
 
 
 
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'))
221
367