~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Vincent Ladeuil
  • Date: 2010-10-26 08:08:23 UTC
  • mfrom: (5514.1.1 665100-content-type)
  • mto: This revision was merged to the branch mainline in revision 5516.
  • Revision ID: v.ladeuil+lp@free.fr-20101026080823-3wggo03b7cpn9908
Correctly set the Content-Type header when POSTing http requests

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-2010 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
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests of status command.
18
18
 
19
19
Most of these depend on the particular formatting used.
20
 
As such they really are blackbox tests even though some of the 
 
20
As such they really are blackbox tests even though some of the
21
21
tests are not using self.capture. If we add tests for the programmatic
22
22
interface later, they will be non blackbox tests.
23
23
"""
24
24
 
25
25
from cStringIO import StringIO
26
26
import codecs
27
 
from os import mkdir, chdir
 
27
from os import mkdir, chdir, rmdir, unlink
28
28
import sys
29
29
from tempfile import TemporaryFile
30
30
 
 
31
from bzrlib import (
 
32
    bzrdir,
 
33
    conflicts,
 
34
    errors,
 
35
    osutils,
 
36
    status,
 
37
    )
31
38
import bzrlib.branch
32
 
from bzrlib.builtins import merge
33
 
import bzrlib.bzrdir as bzrdir
34
 
import bzrlib.errors as errors
35
39
from bzrlib.osutils import pathjoin
36
40
from bzrlib.revisionspec import RevisionSpec
37
41
from bzrlib.status import show_tree_status
40
44
 
41
45
 
42
46
class BranchStatus(TestCaseWithTransport):
43
 
    
44
 
    def test_branch_status(self): 
 
47
 
 
48
    def setUp(self):
 
49
        super(BranchStatus, self).setUp()
 
50
        # As TestCase.setUp clears all hooks, we install this default
 
51
        # post_status hook handler for the test.
 
52
        status.hooks.install_named_hook('post_status',
 
53
            status._show_shelve_summary,
 
54
            'bzr status')
 
55
 
 
56
    def assertStatus(self, expected_lines, working_tree,
 
57
        revision=None, short=False, pending=True, verbose=False):
 
58
        """Run status in working_tree and look for output.
 
59
 
 
60
        :param expected_lines: The lines to look for.
 
61
        :param working_tree: The tree to run status in.
 
62
        """
 
63
        output_string = self.status_string(working_tree, revision, short,
 
64
                pending, verbose)
 
65
        self.assertEqual(expected_lines, output_string.splitlines(True))
 
66
 
 
67
    def status_string(self, wt, revision=None, short=False, pending=True,
 
68
        verbose=False):
 
69
        # use a real file rather than StringIO because it doesn't handle
 
70
        # Unicode very well.
 
71
        tof = codecs.getwriter('utf-8')(TemporaryFile())
 
72
        show_tree_status(wt, to_file=tof, revision=revision, short=short,
 
73
                show_pending=pending, verbose=verbose)
 
74
        tof.seek(0)
 
75
        return tof.read().decode('utf-8')
 
76
 
 
77
    def test_branch_status(self):
45
78
        """Test basic branch status"""
46
79
        wt = self.make_branch_and_tree('.')
47
 
        b = wt.branch
48
 
 
49
 
        # status with nothing
50
 
        tof = StringIO()
51
 
        show_tree_status(wt, to_file=tof)
52
 
        self.assertEquals(tof.getvalue(), "")
53
 
 
54
 
        tof = StringIO()
 
80
 
 
81
        # status with no commits or files - it must
 
82
        # work and show no output. We do this with no
 
83
        # commits to be sure that it's not going to fail
 
84
        # as a corner case.
 
85
        self.assertStatus([], wt)
 
86
 
55
87
        self.build_tree(['hello.c', 'bye.c'])
56
 
        wt.add_pending_merge('pending@pending-0-0')
57
 
        show_tree_status(wt, to_file=tof)
58
 
        tof.seek(0)
59
 
        self.assertEquals(tof.readlines(),
60
 
                          ['unknown:\n',
61
 
                           '  bye.c\n',
62
 
                           '  hello.c\n',
63
 
                           'pending merges:\n',
64
 
                           '  pending@pending-0-0\n'
65
 
                           ])
 
88
        self.assertStatus([
 
89
                'unknown:\n',
 
90
                '  bye.c\n',
 
91
                '  hello.c\n',
 
92
            ],
 
93
            wt)
 
94
        self.assertStatus([
 
95
                '?   bye.c\n',
 
96
                '?   hello.c\n',
 
97
            ],
 
98
            wt, short=True)
 
99
 
 
100
        # add a commit to allow showing pending merges.
 
101
        wt.commit('create a parent to allow testing merge output')
 
102
 
 
103
        wt.add_parent_tree_id('pending@pending-0-0')
 
104
        self.assertStatus([
 
105
                'unknown:\n',
 
106
                '  bye.c\n',
 
107
                '  hello.c\n',
 
108
                'pending merge tips: (use -v to see all merge revisions)\n',
 
109
                '  (ghost) pending@pending-0-0\n',
 
110
            ],
 
111
            wt)
 
112
        self.assertStatus([
 
113
                'unknown:\n',
 
114
                '  bye.c\n',
 
115
                '  hello.c\n',
 
116
                'pending merges:\n',
 
117
                '  (ghost) pending@pending-0-0\n',
 
118
            ],
 
119
            wt, verbose=True)
 
120
        self.assertStatus([
 
121
                '?   bye.c\n',
 
122
                '?   hello.c\n',
 
123
                'P   (ghost) pending@pending-0-0\n',
 
124
            ],
 
125
            wt, short=True)
 
126
        self.assertStatus([
 
127
                'unknown:\n',
 
128
                '  bye.c\n',
 
129
                '  hello.c\n',
 
130
            ],
 
131
            wt, pending=False)
 
132
        self.assertStatus([
 
133
                '?   bye.c\n',
 
134
                '?   hello.c\n',
 
135
            ],
 
136
            wt, short=True, pending=False)
66
137
 
67
138
    def test_branch_status_revisions(self):
68
139
        """Tests branch status with revisions"""
69
140
        wt = self.make_branch_and_tree('.')
70
 
        b = wt.branch
71
141
 
72
 
        tof = StringIO()
73
142
        self.build_tree(['hello.c', 'bye.c'])
74
143
        wt.add('hello.c')
75
144
        wt.add('bye.c')
76
145
        wt.commit('Test message')
77
146
 
78
 
        tof = StringIO()
79
 
        revs =[]
80
 
        revs.append(RevisionSpec(0))
81
 
        
82
 
        show_tree_status(wt, to_file=tof, revision=revs)
83
 
        
84
 
        tof.seek(0)
85
 
        self.assertEquals(tof.readlines(),
86
 
                          ['added:\n',
87
 
                           '  bye.c\n',
88
 
                           '  hello.c\n'])
 
147
        revs = [RevisionSpec.from_string('0')]
 
148
        self.assertStatus([
 
149
                'added:\n',
 
150
                '  bye.c\n',
 
151
                '  hello.c\n'
 
152
            ],
 
153
            wt,
 
154
            revision=revs)
89
155
 
90
156
        self.build_tree(['more.c'])
91
157
        wt.add('more.c')
92
158
        wt.commit('Another test message')
93
 
        
94
 
        tof = StringIO()
95
 
        revs.append(RevisionSpec(1))
96
 
        
97
 
        show_tree_status(wt, to_file=tof, revision=revs)
98
 
        
99
 
        tof.seek(0)
100
 
        self.assertEquals(tof.readlines(),
101
 
                          ['added:\n',
102
 
                           '  bye.c\n',
103
 
                           '  hello.c\n'])
104
159
 
105
 
    def status_string(self, wt):
106
 
        # use a real file rather than StringIO because it doesn't handle
107
 
        # Unicode very well.
108
 
        tof = codecs.getwriter('utf-8')(TemporaryFile())
109
 
        show_tree_status(wt, to_file=tof)
110
 
        tof.seek(0)
111
 
        return tof.read().decode('utf-8')
 
160
        revs.append(RevisionSpec.from_string('1'))
 
161
        self.assertStatus([
 
162
                'added:\n',
 
163
                '  bye.c\n',
 
164
                '  hello.c\n',
 
165
            ],
 
166
            wt,
 
167
            revision=revs)
112
168
 
113
169
    def test_pending(self):
114
170
        """Pending merges display works, including Unicode"""
120
176
        b_2 = b_2_dir.open_branch()
121
177
        wt2 = b_2_dir.open_workingtree()
122
178
        wt.commit(u"\N{TIBETAN DIGIT TWO} Empty commit 2")
123
 
        merge(["./branch", -1], [None, None], this_dir = './copy')
124
 
        message = self.status_string(wt2)
125
 
        self.assert_(message.startswith("pending merges:\n"))
126
 
        self.assert_(message.endswith("Empty commit 2\n")) 
 
179
        wt2.merge_from_branch(wt.branch)
 
180
        message = self.status_string(wt2, verbose=True)
 
181
        self.assertStartsWith(message, "pending merges:\n")
 
182
        self.assertEndsWith(message, "Empty commit 2\n")
127
183
        wt2.commit("merged")
128
184
        # must be long to make sure we see elipsis at the end
129
 
        wt.commit("Empty commit 3 " + 
130
 
                   "blah blah blah blah " * 10)
131
 
        merge(["./branch", -1], [None, None], this_dir = './copy')
132
 
        message = self.status_string(wt2)
133
 
        self.assert_(message.startswith("pending merges:\n"))
 
185
        wt.commit("Empty commit 3 " +
 
186
                   "blah blah blah blah " * 100)
 
187
        wt2.merge_from_branch(wt.branch)
 
188
        message = self.status_string(wt2, verbose=True)
 
189
        self.assertStartsWith(message, "pending merges:\n")
134
190
        self.assert_("Empty commit 3" in message)
135
 
        self.assert_(message.endswith("...\n")) 
136
 
 
137
 
    def test_branch_status_specific_files(self): 
 
191
        self.assertEndsWith(message, "...\n")
 
192
 
 
193
    def test_tree_status_ignores(self):
 
194
        """Tests branch status with ignores"""
 
195
        wt = self.make_branch_and_tree('.')
 
196
        self.run_bzr('ignore *~')
 
197
        wt.commit('commit .bzrignore')
 
198
        self.build_tree(['foo.c', 'foo.c~'])
 
199
        self.assertStatus([
 
200
                'unknown:\n',
 
201
                '  foo.c\n',
 
202
                ],
 
203
                wt)
 
204
        self.assertStatus([
 
205
                '?   foo.c\n',
 
206
                ],
 
207
                wt, short=True)
 
208
 
 
209
    def test_tree_status_specific_files(self):
138
210
        """Tests branch status with given specific files"""
139
211
        wt = self.make_branch_and_tree('.')
140
212
        b = wt.branch
143
215
        wt.add('directory')
144
216
        wt.add('test.c')
145
217
        wt.commit('testing')
146
 
        
 
218
 
 
219
        self.assertStatus([
 
220
                'unknown:\n',
 
221
                '  bye.c\n',
 
222
                '  dir2/\n',
 
223
                '  directory/hello.c\n'
 
224
                ],
 
225
                wt)
 
226
 
 
227
        self.assertStatus([
 
228
                '?   bye.c\n',
 
229
                '?   dir2/\n',
 
230
                '?   directory/hello.c\n'
 
231
                ],
 
232
                wt, short=True)
 
233
 
147
234
        tof = StringIO()
148
 
        show_tree_status(wt, to_file=tof)
149
 
        tof.seek(0)
150
 
        self.assertEquals(tof.readlines(),
151
 
                          ['unknown:\n',
152
 
                           '  bye.c\n',
153
 
                           '  dir2\n',
154
 
                           '  directory/hello.c\n'
155
 
                           ])
156
 
 
157
235
        self.assertRaises(errors.PathsDoNotExist,
158
236
                          show_tree_status,
159
 
                          wt, specific_files=['bye.c','test.c','absent.c'], 
 
237
                          wt, specific_files=['bye.c','test.c','absent.c'],
160
238
                          to_file=tof)
161
 
        
 
239
 
162
240
        tof = StringIO()
163
241
        show_tree_status(wt, specific_files=['directory'], to_file=tof)
164
242
        tof.seek(0)
167
245
                           '  directory/hello.c\n'
168
246
                           ])
169
247
        tof = StringIO()
 
248
        show_tree_status(wt, specific_files=['directory'], to_file=tof,
 
249
                         short=True)
 
250
        tof.seek(0)
 
251
        self.assertEquals(tof.readlines(), ['?   directory/hello.c\n'])
 
252
 
 
253
        tof = StringIO()
170
254
        show_tree_status(wt, specific_files=['dir2'], to_file=tof)
171
255
        tof.seek(0)
172
256
        self.assertEquals(tof.readlines(),
173
257
                          ['unknown:\n',
174
 
                           '  dir2\n'
 
258
                           '  dir2/\n'
175
259
                           ])
 
260
        tof = StringIO()
 
261
        show_tree_status(wt, specific_files=['dir2'], to_file=tof, short=True)
 
262
        tof.seek(0)
 
263
        self.assertEquals(tof.readlines(), ['?   dir2/\n'])
 
264
 
 
265
        tof = StringIO()
 
266
        revs = [RevisionSpec.from_string('0'), RevisionSpec.from_string('1')]
 
267
        show_tree_status(wt, specific_files=['test.c'], to_file=tof,
 
268
                         short=True, revision=revs)
 
269
        tof.seek(0)
 
270
        self.assertEquals(tof.readlines(), ['+N  test.c\n'])
 
271
 
 
272
    def test_specific_files_conflicts(self):
 
273
        tree = self.make_branch_and_tree('.')
 
274
        self.build_tree(['dir2/'])
 
275
        tree.add('dir2')
 
276
        tree.commit('added dir2')
 
277
        tree.set_conflicts(conflicts.ConflictList(
 
278
            [conflicts.ContentsConflict('foo')]))
 
279
        tof = StringIO()
 
280
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
281
        self.assertEqualDiff('', tof.getvalue())
 
282
        tree.set_conflicts(conflicts.ConflictList(
 
283
            [conflicts.ContentsConflict('dir2')]))
 
284
        tof = StringIO()
 
285
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
286
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2\n',
 
287
                             tof.getvalue())
 
288
 
 
289
        tree.set_conflicts(conflicts.ConflictList(
 
290
            [conflicts.ContentsConflict('dir2/file1')]))
 
291
        tof = StringIO()
 
292
        show_tree_status(tree, specific_files=['dir2'], to_file=tof)
 
293
        self.assertEqualDiff('conflicts:\n  Contents conflict in dir2/file1\n',
 
294
                             tof.getvalue())
 
295
 
 
296
    def _prepare_nonexistent(self):
 
297
        wt = self.make_branch_and_tree('.')
 
298
        self.assertStatus([], wt)
 
299
        self.build_tree(['FILE_A', 'FILE_B', 'FILE_C', 'FILE_D', 'FILE_E', ])
 
300
        wt.add('FILE_A')
 
301
        wt.add('FILE_B')
 
302
        wt.add('FILE_C')
 
303
        wt.add('FILE_D')
 
304
        wt.add('FILE_E')
 
305
        wt.commit('Create five empty files.')
 
306
        open('FILE_B', 'w').write('Modification to file FILE_B.')
 
307
        open('FILE_C', 'w').write('Modification to file FILE_C.')
 
308
        unlink('FILE_E')  # FILE_E will be versioned but missing
 
309
        open('FILE_Q', 'w').write('FILE_Q is added but not committed.')
 
310
        wt.add('FILE_Q')  # FILE_Q will be added but not committed
 
311
        open('UNVERSIONED_BUT_EXISTING', 'w')
 
312
        return wt
176
313
 
177
314
    def test_status_nonexistent_file(self):
178
315
        # files that don't exist in either the basis tree or working tree
179
316
        # should give an error
 
317
        wt = self._prepare_nonexistent()
 
318
        self.assertStatus([
 
319
            'removed:\n',
 
320
            '  FILE_E\n',
 
321
            'added:\n',
 
322
            '  FILE_Q\n',
 
323
            'modified:\n',
 
324
            '  FILE_B\n',
 
325
            '  FILE_C\n',
 
326
            'unknown:\n',
 
327
            '  UNVERSIONED_BUT_EXISTING\n',
 
328
            ],
 
329
            wt)
 
330
        self.assertStatus([
 
331
            ' M  FILE_B\n',
 
332
            ' M  FILE_C\n',
 
333
            ' D  FILE_E\n',
 
334
            '+N  FILE_Q\n',
 
335
            '?   UNVERSIONED_BUT_EXISTING\n',
 
336
            ],
 
337
            wt, short=True)
 
338
 
 
339
        # Okay, everything's looking good with the existent files.
 
340
        # Let's see what happens when we throw in non-existent files.
 
341
 
 
342
        # bzr st [--short] NONEXISTENT '
 
343
        expected = [
 
344
          'nonexistent:\n',
 
345
          '  NONEXISTENT\n',
 
346
          ]
 
347
        out, err = self.run_bzr('status NONEXISTENT', retcode=3)
 
348
        self.assertEqual(expected, out.splitlines(True))
 
349
        self.assertContainsRe(err,
 
350
                              r'.*ERROR: Path\(s\) do not exist: '
 
351
                              'NONEXISTENT.*')
 
352
        expected = [
 
353
          'X:   NONEXISTENT\n',
 
354
          ]
 
355
        out, err = self.run_bzr('status --short NONEXISTENT', retcode=3)
 
356
        self.assertContainsRe(err,
 
357
                              r'.*ERROR: Path\(s\) do not exist: '
 
358
                              'NONEXISTENT.*')
 
359
 
 
360
    def test_status_nonexistent_file_with_others(self):
 
361
        # bzr st [--short] NONEXISTENT ...others..
 
362
        wt = self._prepare_nonexistent()
 
363
        expected = [
 
364
          'removed:\n',
 
365
          '  FILE_E\n',
 
366
          'modified:\n',
 
367
          '  FILE_B\n',
 
368
          '  FILE_C\n',
 
369
          'nonexistent:\n',
 
370
          '  NONEXISTENT\n',
 
371
          ]
 
372
        out, err = self.run_bzr('status NONEXISTENT '
 
373
                                'FILE_A FILE_B FILE_C FILE_D FILE_E',
 
374
                                retcode=3)
 
375
        self.assertEqual(expected, out.splitlines(True))
 
376
        self.assertContainsRe(err,
 
377
                              r'.*ERROR: Path\(s\) do not exist: '
 
378
                              'NONEXISTENT.*')
 
379
        expected = [
 
380
          ' D  FILE_E\n',
 
381
          ' M  FILE_C\n',
 
382
          ' M  FILE_B\n',
 
383
          'X   NONEXISTENT\n',
 
384
          ]
 
385
        out, err = self.run_bzr('status --short NONEXISTENT '
 
386
                                'FILE_A FILE_B FILE_C FILE_D FILE_E',
 
387
                                retcode=3)
 
388
        self.assertEqual(expected, out.splitlines(True))
 
389
        self.assertContainsRe(err,
 
390
                              r'.*ERROR: Path\(s\) do not exist: '
 
391
                              'NONEXISTENT.*')
 
392
 
 
393
    def test_status_multiple_nonexistent_files(self):
 
394
        # bzr st [--short] NONEXISTENT ... ANOTHER_NONEXISTENT ...
 
395
        wt = self._prepare_nonexistent()
 
396
        expected = [
 
397
          'removed:\n',
 
398
          '  FILE_E\n',
 
399
          'modified:\n',
 
400
          '  FILE_B\n',
 
401
          '  FILE_C\n',
 
402
          'nonexistent:\n',
 
403
          '  ANOTHER_NONEXISTENT\n',
 
404
          '  NONEXISTENT\n',
 
405
          ]
 
406
        out, err = self.run_bzr('status NONEXISTENT '
 
407
                                'FILE_A FILE_B ANOTHER_NONEXISTENT '
 
408
                                'FILE_C FILE_D FILE_E', retcode=3)
 
409
        self.assertEqual(expected, out.splitlines(True))
 
410
        self.assertContainsRe(err,
 
411
                              r'.*ERROR: Path\(s\) do not exist: '
 
412
                              'ANOTHER_NONEXISTENT NONEXISTENT.*')
 
413
        expected = [
 
414
          ' D  FILE_E\n',
 
415
          ' M  FILE_C\n',
 
416
          ' M  FILE_B\n',
 
417
          'X   ANOTHER_NONEXISTENT\n',
 
418
          'X   NONEXISTENT\n',
 
419
          ]
 
420
        out, err = self.run_bzr('status --short NONEXISTENT '
 
421
                                'FILE_A FILE_B ANOTHER_NONEXISTENT '
 
422
                                'FILE_C FILE_D FILE_E', retcode=3)
 
423
        self.assertEqual(expected, out.splitlines(True))
 
424
        self.assertContainsRe(err,
 
425
                              r'.*ERROR: Path\(s\) do not exist: '
 
426
                              'ANOTHER_NONEXISTENT NONEXISTENT.*')
 
427
 
 
428
    def test_status_nonexistent_file_with_unversioned(self):
 
429
        # bzr st [--short] NONEXISTENT A B UNVERSIONED_BUT_EXISTING C D E Q
 
430
        wt = self._prepare_nonexistent()
 
431
        expected = [
 
432
          'removed:\n',
 
433
          '  FILE_E\n',
 
434
          'added:\n',
 
435
          '  FILE_Q\n',
 
436
          'modified:\n',
 
437
          '  FILE_B\n',
 
438
          '  FILE_C\n',
 
439
          'unknown:\n',
 
440
          '  UNVERSIONED_BUT_EXISTING\n',
 
441
          'nonexistent:\n',
 
442
          '  NONEXISTENT\n',
 
443
          ]
 
444
        out, err = self.run_bzr('status NONEXISTENT '
 
445
                                'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
 
446
                                'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
 
447
        self.assertEqual(expected, out.splitlines(True))
 
448
        self.assertContainsRe(err,
 
449
                              r'.*ERROR: Path\(s\) do not exist: '
 
450
                              'NONEXISTENT.*')
 
451
        expected = [
 
452
          '+N  FILE_Q\n',
 
453
          '?   UNVERSIONED_BUT_EXISTING\n',
 
454
          ' D  FILE_E\n',
 
455
          ' M  FILE_C\n',
 
456
          ' M  FILE_B\n',
 
457
          'X   NONEXISTENT\n',
 
458
          ]
 
459
        out, err = self.run_bzr('status --short NONEXISTENT '
 
460
                                'FILE_A FILE_B UNVERSIONED_BUT_EXISTING '
 
461
                                'FILE_C FILE_D FILE_E FILE_Q', retcode=3)
 
462
        self.assertEqual(expected, out.splitlines(True))
 
463
        self.assertContainsRe(err,
 
464
                              r'.*ERROR: Path\(s\) do not exist: '
 
465
                              'NONEXISTENT.*')
 
466
 
 
467
    def test_status_out_of_date(self):
 
468
        """Simulate status of out-of-date tree after remote push"""
 
469
        tree = self.make_branch_and_tree('.')
 
470
        self.build_tree_contents([('a', 'foo\n')])
 
471
        tree.lock_write()
 
472
        try:
 
473
            tree.add(['a'])
 
474
            tree.commit('add test file')
 
475
            # simulate what happens after a remote push
 
476
            tree.set_last_revision("0")
 
477
        finally:
 
478
            # before run another commands we should unlock tree
 
479
            tree.unlock()
 
480
        out, err = self.run_bzr('status')
 
481
        self.assertEqual("working tree is out of date, run 'bzr update'\n",
 
482
                         err)
 
483
 
 
484
    def test_status_on_ignored(self):
 
485
        """Tests branch status on an unversioned file which is considered ignored.
 
486
 
 
487
        See https://bugs.launchpad.net/bzr/+bug/40103
 
488
        """
 
489
        tree = self.make_branch_and_tree('.')
 
490
 
 
491
        self.build_tree(['test1.c', 'test1.c~', 'test2.c~'])
 
492
        result = self.run_bzr('status')[0]
 
493
        self.assertContainsRe(result, "unknown:\n  test1.c\n")
 
494
        short_result = self.run_bzr('status --short')[0]
 
495
        self.assertContainsRe(short_result, "\?   test1.c\n")
 
496
 
 
497
        result = self.run_bzr('status test1.c')[0]
 
498
        self.assertContainsRe(result, "unknown:\n  test1.c\n")
 
499
        short_result = self.run_bzr('status --short test1.c')[0]
 
500
        self.assertContainsRe(short_result, "\?   test1.c\n")
 
501
 
 
502
        result = self.run_bzr('status test1.c~')[0]
 
503
        self.assertContainsRe(result, "ignored:\n  test1.c~\n")
 
504
        short_result = self.run_bzr('status --short test1.c~')[0]
 
505
        self.assertContainsRe(short_result, "I   test1.c~\n")
 
506
 
 
507
        result = self.run_bzr('status test1.c~ test2.c~')[0]
 
508
        self.assertContainsRe(result, "ignored:\n  test1.c~\n  test2.c~\n")
 
509
        short_result = self.run_bzr('status --short test1.c~ test2.c~')[0]
 
510
        self.assertContainsRe(short_result, "I   test1.c~\nI   test2.c~\n")
 
511
 
 
512
        result = self.run_bzr('status test1.c test1.c~ test2.c~')[0]
 
513
        self.assertContainsRe(result, "unknown:\n  test1.c\nignored:\n  test1.c~\n  test2.c~\n")
 
514
        short_result = self.run_bzr('status --short test1.c test1.c~ test2.c~')[0]
 
515
        self.assertContainsRe(short_result, "\?   test1.c\nI   test1.c~\nI   test2.c~\n")
 
516
 
 
517
    def test_status_write_lock(self):
 
518
        """Test that status works without fetching history and
 
519
        having a write lock.
 
520
 
 
521
        See https://bugs.launchpad.net/bzr/+bug/149270
 
522
        """
 
523
        mkdir('branch1')
 
524
        wt = self.make_branch_and_tree('branch1')
 
525
        b = wt.branch
 
526
        wt.commit('Empty commit 1')
 
527
        wt2 = b.bzrdir.sprout('branch2').open_workingtree()
 
528
        wt2.commit('Empty commit 2')
 
529
        out, err = self.run_bzr('status branch1 -rbranch:branch2')
 
530
        self.assertEqual('', out)
 
531
 
 
532
    def test_status_with_shelves(self):
 
533
        """Ensure that _show_shelve_summary handler works.
 
534
        """
180
535
        wt = self.make_branch_and_tree('.')
181
 
        out, err = self.run_bzr('status', 'does-not-exist', retcode=3)
182
 
        self.assertContainsRe(err, r'do not exist.*does-not-exist')
 
536
        self.build_tree(['hello.c'])
 
537
        wt.add('hello.c')
 
538
        self.run_bzr(['shelve', '--all', '-m', 'foo'])
 
539
        self.build_tree(['bye.c'])
 
540
        wt.add('bye.c')
 
541
        self.assertStatus([
 
542
                'added:\n',
 
543
                '  bye.c\n',
 
544
                '1 shelves exist. See "bzr shelve --list" for details.\n',
 
545
            ],
 
546
            wt)
183
547
 
184
548
 
185
549
class CheckoutStatus(BranchStatus):
188
552
        super(CheckoutStatus, self).setUp()
189
553
        mkdir('codir')
190
554
        chdir('codir')
191
 
        
 
555
 
192
556
    def make_branch_and_tree(self, relpath):
193
557
        source = self.make_branch(pathjoin('..', relpath))
194
558
        checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
195
 
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
 
559
        bzrlib.branch.BranchReferenceFormat().initialize(checkout,
 
560
            target_branch=source)
196
561
        return checkout.create_workingtree()
197
562
 
198
563
 
199
564
class TestStatus(TestCaseWithTransport):
200
565
 
201
 
    def test_status(self):
202
 
        self.run_bzr("init")
203
 
        self.build_tree(['hello.txt'])
204
 
        result = self.run_bzr("status")[0]
205
 
        self.assert_("unknown:\n  hello.txt\n" in result, result)
206
 
        self.run_bzr("add", "hello.txt")
207
 
        result = self.run_bzr("status")[0]
208
 
        self.assert_("added:\n  hello.txt\n" in result, result)
209
 
        self.run_bzr("commit", "-m", "added")
210
 
        result = self.run_bzr("status", "-r", "0..1")[0]
211
 
        self.assert_("added:\n  hello.txt\n" in result, result)
212
 
        self.build_tree(['world.txt'])
213
 
        result = self.run_bzr("status", "-r", "0")[0]
214
 
        self.assert_("added:\n  hello.txt\n" \
215
 
                     "unknown:\n  world.txt\n" in result, result)
216
 
 
217
 
        result2 = self.run_bzr("status", "-r", "0..")[0]
218
 
        self.assertEquals(result2, result)
 
566
    def test_status_plain(self):
 
567
        tree = self.make_branch_and_tree('.')
 
568
 
 
569
        self.build_tree(['hello.txt'])
 
570
        result = self.run_bzr("status")[0]
 
571
        self.assertContainsRe(result, "unknown:\n  hello.txt\n")
 
572
 
 
573
        tree.add("hello.txt")
 
574
        result = self.run_bzr("status")[0]
 
575
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
576
 
 
577
        tree.commit(message="added")
 
578
        result = self.run_bzr("status -r 0..1")[0]
 
579
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
580
 
 
581
        result = self.run_bzr("status -c 1")[0]
 
582
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
583
 
 
584
        self.build_tree(['world.txt'])
 
585
        result = self.run_bzr("status -r 0")[0]
 
586
        self.assertContainsRe(result, "added:\n  hello.txt\n" \
 
587
                                      "unknown:\n  world.txt\n")
 
588
        result2 = self.run_bzr("status -r 0..")[0]
 
589
        self.assertEquals(result2, result)
 
590
 
 
591
    def test_status_short(self):
 
592
        tree = self.make_branch_and_tree('.')
 
593
 
 
594
        self.build_tree(['hello.txt'])
 
595
        result = self.run_bzr("status --short")[0]
 
596
        self.assertContainsRe(result, "[?]   hello.txt\n")
 
597
 
 
598
        tree.add("hello.txt")
 
599
        result = self.run_bzr("status --short")[0]
 
600
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
601
 
 
602
        tree.commit(message="added")
 
603
        result = self.run_bzr("status --short -r 0..1")[0]
 
604
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
605
 
 
606
        self.build_tree(['world.txt'])
 
607
        result = self.run_bzr("status --short -r 0")[0]
 
608
        self.assertContainsRe(result, "[+]N  hello.txt\n" \
 
609
                                      "[?]   world.txt\n")
 
610
        result2 = self.run_bzr("status --short -r 0..")[0]
 
611
        self.assertEquals(result2, result)
 
612
 
 
613
    def test_status_versioned(self):
 
614
        tree = self.make_branch_and_tree('.')
 
615
 
 
616
        self.build_tree(['hello.txt'])
 
617
        result = self.run_bzr("status --versioned")[0]
 
618
        self.assertNotContainsRe(result, "unknown:\n  hello.txt\n")
 
619
 
 
620
        tree.add("hello.txt")
 
621
        result = self.run_bzr("status --versioned")[0]
 
622
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
623
 
 
624
        tree.commit("added")
 
625
        result = self.run_bzr("status --versioned -r 0..1")[0]
 
626
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
627
 
 
628
        self.build_tree(['world.txt'])
 
629
        result = self.run_bzr("status --versioned -r 0")[0]
 
630
        self.assertContainsRe(result, "added:\n  hello.txt\n")
 
631
        self.assertNotContainsRe(result, "unknown:\n  world.txt\n")
 
632
        result2 = self.run_bzr("status --versioned -r 0..")[0]
 
633
        self.assertEquals(result2, result)
 
634
 
 
635
    def test_status_SV(self):
 
636
        tree = self.make_branch_and_tree('.')
 
637
 
 
638
        self.build_tree(['hello.txt'])
 
639
        result = self.run_bzr("status -SV")[0]
 
640
        self.assertNotContainsRe(result, "hello.txt")
 
641
 
 
642
        tree.add("hello.txt")
 
643
        result = self.run_bzr("status -SV")[0]
 
644
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
645
 
 
646
        tree.commit(message="added")
 
647
        result = self.run_bzr("status -SV -r 0..1")[0]
 
648
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
649
 
 
650
        self.build_tree(['world.txt'])
 
651
        result = self.run_bzr("status -SV -r 0")[0]
 
652
        self.assertContainsRe(result, "[+]N  hello.txt\n")
 
653
 
 
654
        result2 = self.run_bzr("status -SV -r 0..")[0]
 
655
        self.assertEquals(result2, result)
 
656
 
 
657
    def assertStatusContains(self, pattern, short=False):
 
658
        """Run status, and assert it contains the given pattern"""
 
659
        if short:
 
660
            result = self.run_bzr("status --short")[0]
 
661
        else:
 
662
            result = self.run_bzr("status")[0]
 
663
        self.assertContainsRe(result, pattern)
 
664
 
 
665
    def test_kind_change_plain(self):
 
666
        tree = self.make_branch_and_tree('.')
 
667
        self.build_tree(['file'])
 
668
        tree.add('file')
 
669
        tree.commit('added file')
 
670
        unlink('file')
 
671
        self.build_tree(['file/'])
 
672
        self.assertStatusContains('kind changed:\n  file \(file => directory\)')
 
673
        tree.rename_one('file', 'directory')
 
674
        self.assertStatusContains('renamed:\n  file/ => directory/\n' \
 
675
                                  'modified:\n  directory/\n')
 
676
        rmdir('directory')
 
677
        self.assertStatusContains('removed:\n  file\n')
 
678
 
 
679
    def test_kind_change_short(self):
 
680
        tree = self.make_branch_and_tree('.')
 
681
        self.build_tree(['file'])
 
682
        tree.add('file')
 
683
        tree.commit('added file')
 
684
        unlink('file')
 
685
        self.build_tree(['file/'])
 
686
        self.assertStatusContains('K  file => file/',
 
687
                                   short=True)
 
688
        tree.rename_one('file', 'directory')
 
689
        self.assertStatusContains('RK  file => directory/',
 
690
                                   short=True)
 
691
        rmdir('directory')
 
692
        self.assertStatusContains('RD  file => directory',
 
693
                                   short=True)
 
694
 
 
695
    def test_status_illegal_revision_specifiers(self):
 
696
        out, err = self.run_bzr('status -r 1..23..123', retcode=3)
 
697
        self.assertContainsRe(err, 'one or two revision specifiers')
 
698
 
 
699
    def test_status_no_pending(self):
 
700
        a_tree = self.make_branch_and_tree('a')
 
701
        self.build_tree(['a/a'])
 
702
        a_tree.add('a')
 
703
        a_tree.commit('a')
 
704
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
705
        self.build_tree(['b/b'])
 
706
        b_tree.add('b')
 
707
        b_tree.commit('b')
 
708
 
 
709
        self.run_bzr('merge ../b', working_dir='a')
 
710
        out, err = self.run_bzr('status --no-pending', working_dir='a')
 
711
        self.assertEquals(out, "added:\n  b\n")
 
712
 
 
713
    def test_pending_specific_files(self):
 
714
        """With a specific file list, pending merges are not shown."""
 
715
        tree = self.make_branch_and_tree('tree')
 
716
        self.build_tree_contents([('tree/a', 'content of a\n')])
 
717
        tree.add('a')
 
718
        r1_id = tree.commit('one')
 
719
        alt = tree.bzrdir.sprout('alt').open_workingtree()
 
720
        self.build_tree_contents([('alt/a', 'content of a\nfrom alt\n')])
 
721
        alt_id = alt.commit('alt')
 
722
        tree.merge_from_branch(alt.branch)
 
723
        output = self.make_utf8_encoded_stringio()
 
724
        show_tree_status(tree, to_file=output)
 
725
        self.assertContainsRe(output.getvalue(), 'pending merge')
 
726
        out, err = self.run_bzr('status tree/a')
 
727
        self.assertNotContainsRe(out, 'pending merge')
219
728
 
220
729
 
221
730
class TestStatusEncodings(TestCaseWithTransport):
222
 
    
223
 
    def setUp(self):
224
 
        TestCaseWithTransport.setUp(self)
225
 
        self.user_encoding = bzrlib.user_encoding
226
 
        self.stdout = sys.stdout
227
 
 
228
 
    def tearDown(self):
229
 
        bzrlib.user_encoding = self.user_encoding
230
 
        sys.stdout = self.stdout
231
 
        TestCaseWithTransport.tearDown(self)
232
731
 
233
732
    def make_uncommitted_tree(self):
234
733
        """Build a branch with uncommitted unicode named changes in the cwd."""
243
742
        return working_tree
244
743
 
245
744
    def test_stdout_ascii(self):
246
 
        sys.stdout = StringIO()
247
 
        bzrlib.user_encoding = 'ascii'
 
745
        self.overrideAttr(osutils, '_cached_user_encoding', 'ascii')
248
746
        working_tree = self.make_uncommitted_tree()
249
747
        stdout, stderr = self.run_bzr("status")
250
748
 
254
752
""")
255
753
 
256
754
    def test_stdout_latin1(self):
257
 
        sys.stdout = StringIO()
258
 
        bzrlib.user_encoding = 'latin-1'
 
755
        self.overrideAttr(osutils, '_cached_user_encoding', 'latin-1')
259
756
        working_tree = self.make_uncommitted_tree()
260
757
        stdout, stderr = self.run_bzr('status')
261
758