~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Martin Packman
  • Date: 2012-02-01 13:24:42 UTC
  • mto: (6437.23.4 2.5)
  • mto: This revision was merged to the branch mainline in revision 6462.
  • Revision ID: martin.packman@canonical.com-20120201132442-ela7jc4mxv4b058o
Treat path for .bzr.log as unicode

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
 
 
 
3
#
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
6
6
# the Free Software Foundation; either version 2 of the License, or
7
7
# (at your option) any later version.
8
 
 
 
8
#
9
9
# This program is distributed in the hope that it will be useful,
10
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
12
# GNU General Public License for more details.
13
 
 
 
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
 
18
18
 
19
19
"""Black-box tests for bzr.
20
20
 
21
21
These check that it behaves properly when it's invoked through the regular
22
 
command-line interface. This doesn't actually run a new interpreter but 
 
22
command-line interface. This doesn't actually run a new interpreter but
23
23
rather starts again from the run_bzr function.
24
24
"""
25
25
 
26
26
 
27
 
from cStringIO import StringIO
28
 
import os
29
 
import shutil
30
 
import sys
31
 
import os
32
 
 
33
 
from bzrlib.branch import Branch
34
 
from bzrlib.clone import copy_branch
35
 
from bzrlib.errors import BzrCommandError
36
 
from bzrlib.osutils import has_symlinks
37
 
from bzrlib.selftest import TestCaseInTempDir, BzrTestBase
38
 
from bzrlib.annotate import annotate_file
39
 
 
40
 
 
41
 
class TestAnnotate(TestCaseInTempDir):
 
27
from bzrlib import (
 
28
    config,
 
29
    tests,
 
30
    )
 
31
 
 
32
from bzrlib.tests.matchers import ContainsNoVfsCalls
 
33
from bzrlib.urlutils import joinpath
 
34
 
 
35
 
 
36
class TestAnnotate(tests.TestCaseWithTransport):
 
37
 
42
38
    def setUp(self):
43
39
        super(TestAnnotate, self).setUp()
44
 
        b = Branch.initialize('.')
 
40
        wt = self.make_branch_and_tree('.')
 
41
        b = wt.branch
45
42
        self.build_tree_contents([('hello.txt', 'my helicopter\n'),
46
43
                                  ('nomail.txt', 'nomail\n')])
47
 
        b.add(['hello.txt'])
48
 
        b.working_tree().commit('add hello', 
49
 
                                committer='test@user')
50
 
        b.add(['nomail.txt'])
51
 
        b.working_tree().commit('add nomail', committer='no mail')
 
44
        wt.add(['hello.txt'])
 
45
        self.revision_id_1 = wt.commit('add hello',
 
46
                              committer='test@user',
 
47
                              timestamp=1165960000.00, timezone=0)
 
48
        wt.add(['nomail.txt'])
 
49
        self.revision_id_2 = wt.commit('add nomail',
 
50
                              committer='no mail',
 
51
                              timestamp=1165970000.00, timezone=0)
 
52
        self.build_tree_contents([('hello.txt', 'my helicopter\n'
 
53
                                                'your helicopter\n')])
 
54
        self.revision_id_3 = wt.commit('mod hello',
 
55
                              committer='user@test',
 
56
                              timestamp=1166040000.00, timezone=0)
 
57
        self.build_tree_contents([('hello.txt', 'my helicopter\n'
 
58
                                                'your helicopter\n'
 
59
                                                'all of\n'
 
60
                                                'our helicopters\n'
 
61
                                  )])
 
62
        self.revision_id_4 = wt.commit('mod hello',
 
63
                              committer='user@test',
 
64
                              timestamp=1166050000.00, timezone=0)
52
65
 
53
66
    def test_help_annotate(self):
54
67
        """Annotate command exists"""
55
 
        out, err = self.run_bzr_captured(['--no-plugins', 'annotate', '--help'])
 
68
        out, err = self.run_bzr('--no-plugins annotate --help')
56
69
 
57
70
    def test_annotate_cmd(self):
58
 
        out, err = self.run_bzr_captured(['annotate', 'hello.txt'])
59
 
        self.assertEquals(err, '')
60
 
        self.assertEqualDiff(out, '''\
61
 
    1 test@us | my helicopter
62
 
''')
 
71
        out, err = self.run_bzr('annotate hello.txt')
 
72
        self.assertEqual('', err)
 
73
        self.assertEqualDiff('''\
 
74
1   test@us | my helicopter
 
75
3   user@te | your helicopter
 
76
4   user@te | all of
 
77
            | our helicopters
 
78
''', out)
 
79
 
 
80
    def test_annotate_cmd_full(self):
 
81
        out, err = self.run_bzr('annotate hello.txt --all')
 
82
        self.assertEqual('', err)
 
83
        self.assertEqualDiff('''\
 
84
1   test@us | my helicopter
 
85
3   user@te | your helicopter
 
86
4   user@te | all of
 
87
4   user@te | our helicopters
 
88
''', out)
 
89
 
 
90
    def test_annotate_cmd_long(self):
 
91
        out, err = self.run_bzr('annotate hello.txt --long')
 
92
        self.assertEqual('', err)
 
93
        self.assertEqualDiff('''\
 
94
1   test@user 20061212 | my helicopter
 
95
3   user@test 20061213 | your helicopter
 
96
4   user@test 20061213 | all of
 
97
                       | our helicopters
 
98
''', out)
 
99
 
 
100
    def test_annotate_cmd_show_ids(self):
 
101
        out, err = self.run_bzr('annotate hello.txt --show-ids')
 
102
        max_len = max([len(self.revision_id_1),
 
103
                       len(self.revision_id_3),
 
104
                       len(self.revision_id_4)])
 
105
        self.assertEqual('', err)
 
106
        self.assertEqualDiff('''\
 
107
%*s | my helicopter
 
108
%*s | your helicopter
 
109
%*s | all of
 
110
%*s | our helicopters
 
111
''' % (max_len, self.revision_id_1,
 
112
       max_len, self.revision_id_3,
 
113
       max_len, self.revision_id_4,
 
114
       max_len, '',
 
115
      )
 
116
, out)
63
117
 
64
118
    def test_no_mail(self):
65
 
        out, err = self.run_bzr_captured(['annotate', 'nomail.txt'])
66
 
        self.assertEquals(err, '')
67
 
        self.assertEqualDiff(out, '''\
68
 
    2 no mail | nomail
69
 
''')
 
119
        out, err = self.run_bzr('annotate nomail.txt')
 
120
        self.assertEqual('', err)
 
121
        self.assertEqualDiff('''\
 
122
2   no mail | nomail
 
123
''', out)
 
124
 
 
125
    def test_annotate_cmd_revision(self):
 
126
        out, err = self.run_bzr('annotate hello.txt -r1')
 
127
        self.assertEqual('', err)
 
128
        self.assertEqualDiff('''\
 
129
1   test@us | my helicopter
 
130
''', out)
 
131
 
 
132
    def test_annotate_cmd_revision3(self):
 
133
        out, err = self.run_bzr('annotate hello.txt -r3')
 
134
        self.assertEqual('', err)
 
135
        self.assertEqualDiff('''\
 
136
1   test@us | my helicopter
 
137
3   user@te | your helicopter
 
138
''', out)
 
139
 
 
140
    def test_annotate_cmd_unknown_revision(self):
 
141
        out, err = self.run_bzr('annotate hello.txt -r 10',
 
142
                                retcode=3)
 
143
        self.assertEqual('', out)
 
144
        self.assertContainsRe(err, "Requested revision: '10' does not exist")
 
145
 
 
146
    def test_annotate_cmd_two_revisions(self):
 
147
        out, err = self.run_bzr('annotate hello.txt -r1..2',
 
148
                                retcode=3)
 
149
        self.assertEqual('', out)
 
150
        self.assertEqual('bzr: ERROR: bzr annotate --revision takes'
 
151
                         ' exactly one revision identifier\n',
 
152
                         err)
 
153
 
 
154
 
 
155
class TestSimpleAnnotate(tests.TestCaseWithTransport):
 
156
    """Annotate tests with no complex setup."""
 
157
 
 
158
    def _setup_edited_file(self, relpath='.'):
 
159
        """Create a tree with a locally edited file."""
 
160
        tree = self.make_branch_and_tree(relpath)
 
161
        file_relpath = joinpath(relpath, 'file')
 
162
        self.build_tree_contents([(file_relpath, 'foo\ngam\n')])
 
163
        tree.add('file')
 
164
        tree.commit('add file', committer="test@host", rev_id="rev1")
 
165
        self.build_tree_contents([(file_relpath, 'foo\nbar\ngam\n')])
 
166
        return tree
 
167
 
 
168
    def test_annotate_cmd_revspec_branch(self):
 
169
        tree = self._setup_edited_file('trunk')
 
170
        tree.branch.create_checkout(self.get_url('work'), lightweight=True)
 
171
        out, err = self.run_bzr(['annotate', 'file', '-r', 'branch:../trunk'],
 
172
                                working_dir='work')
 
173
        self.assertEqual('', err)
 
174
        self.assertEqual(
 
175
            '1   test@ho | foo\n'
 
176
            '            | gam\n',
 
177
            out)
 
178
 
 
179
    def test_annotate_edited_file(self):
 
180
        tree = self._setup_edited_file()
 
181
        self.overrideEnv('BZR_EMAIL', 'current@host2')
 
182
        out, err = self.run_bzr('annotate file')
 
183
        self.assertEqual(
 
184
            '1   test@ho | foo\n'
 
185
            '2?  current | bar\n'
 
186
            '1   test@ho | gam\n',
 
187
            out)
 
188
 
 
189
    def test_annotate_edited_file_no_default(self):
 
190
        # Ensure that when no username is available annotate still works.
 
191
        self.overrideEnv('EMAIL', None)
 
192
        self.overrideEnv('BZR_EMAIL', None)
 
193
        # Also, make sure that it's not inferred from mailname.
 
194
        self.overrideAttr(config, '_auto_user_id',
 
195
            lambda: (None, None))
 
196
        tree = self._setup_edited_file()
 
197
        out, err = self.run_bzr('annotate file')
 
198
        self.assertEqual(
 
199
            '1   test@ho | foo\n'
 
200
            '2?  local u | bar\n'
 
201
            '1   test@ho | gam\n',
 
202
            out)
 
203
 
 
204
    def test_annotate_edited_file_show_ids(self):
 
205
        tree = self._setup_edited_file()
 
206
        self.overrideEnv('BZR_EMAIL', 'current@host2')
 
207
        out, err = self.run_bzr('annotate file --show-ids')
 
208
        self.assertEqual(
 
209
            '    rev1 | foo\n'
 
210
            'current: | bar\n'
 
211
            '    rev1 | gam\n',
 
212
            out)
 
213
 
 
214
    def _create_merged_file(self):
 
215
        """Create a file with a pending merge and local edit."""
 
216
        tree = self.make_branch_and_tree('.')
 
217
        self.build_tree_contents([('file', 'foo\ngam\n')])
 
218
        tree.add('file')
 
219
        tree.commit('add file', rev_id="rev1", committer="test@host")
 
220
        # right side
 
221
        self.build_tree_contents([('file', 'foo\nbar\ngam\n')])
 
222
        tree.commit("right", rev_id="rev1.1.1", committer="test@host")
 
223
        tree.pull(tree.branch, True, "rev1")
 
224
        # left side
 
225
        self.build_tree_contents([('file', 'foo\nbaz\ngam\n')])
 
226
        tree.commit("left", rev_id="rev2", committer="test@host")
 
227
        # merge
 
228
        tree.merge_from_branch(tree.branch, "rev1.1.1")
 
229
        # edit the file to be 'resolved' and have a further local edit
 
230
        self.build_tree_contents([('file', 'local\nfoo\nbar\nbaz\ngam\n')])
 
231
        return tree
 
232
 
 
233
    def test_annotated_edited_merged_file_revnos(self):
 
234
        wt = self._create_merged_file()
 
235
        out, err = self.run_bzr(['annotate', 'file'])
 
236
        email = config.extract_email_address(wt.branch.get_config().username())
 
237
        self.assertEqual(
 
238
            '3?    %-7s | local\n'
 
239
            '1     test@ho | foo\n'
 
240
            '1.1.1 test@ho | bar\n'
 
241
            '2     test@ho | baz\n'
 
242
            '1     test@ho | gam\n' % email[:7],
 
243
            out)
 
244
 
 
245
    def test_annotated_edited_merged_file_ids(self):
 
246
        self._create_merged_file()
 
247
        out, err = self.run_bzr(['annotate', 'file', '--show-ids'])
 
248
        self.assertEqual(
 
249
            'current: | local\n'
 
250
            '    rev1 | foo\n'
 
251
            'rev1.1.1 | bar\n'
 
252
            '    rev2 | baz\n'
 
253
            '    rev1 | gam\n',
 
254
            out)
 
255
 
 
256
    def test_annotate_empty_file(self):
 
257
        tree = self.make_branch_and_tree('.')
 
258
        self.build_tree_contents([('empty', '')])
 
259
        tree.add('empty')
 
260
        tree.commit('add empty file')
 
261
        out, err = self.run_bzr(['annotate', 'empty'])
 
262
        self.assertEqual('', out)
 
263
 
 
264
    def test_annotate_removed_file(self):
 
265
        tree = self.make_branch_and_tree('.')
 
266
        self.build_tree_contents([('empty', '')])
 
267
        tree.add('empty')
 
268
        tree.commit('add empty file')
 
269
        # delete the file.
 
270
        tree.remove('empty')
 
271
        tree.commit('remove empty file')
 
272
        out, err = self.run_bzr(['annotate', '-r1', 'empty'])
 
273
        self.assertEqual('', out)
 
274
 
 
275
    def test_annotate_empty_file_show_ids(self):
 
276
        tree = self.make_branch_and_tree('.')
 
277
        self.build_tree_contents([('empty', '')])
 
278
        tree.add('empty')
 
279
        tree.commit('add empty file')
 
280
        out, err = self.run_bzr(['annotate', '--show-ids', 'empty'])
 
281
        self.assertEqual('', out)
 
282
 
 
283
    def test_annotate_nonexistant_file(self):
 
284
        tree = self.make_branch_and_tree('.')
 
285
        self.build_tree(['file'])
 
286
        tree.add(['file'])
 
287
        tree.commit('add a file')
 
288
        out, err = self.run_bzr(['annotate', 'doesnotexist'], retcode=3)
 
289
        self.assertEqual('', out)
 
290
        self.assertEqual("bzr: ERROR: doesnotexist is not versioned.\n", err)
 
291
 
 
292
    def test_annotate_without_workingtree(self):
 
293
        tree = self.make_branch_and_tree('.')
 
294
        self.build_tree_contents([('empty', '')])
 
295
        tree.add('empty')
 
296
        tree.commit('add empty file')
 
297
        bzrdir = tree.branch.bzrdir
 
298
        bzrdir.destroy_workingtree()
 
299
        self.assertFalse(bzrdir.has_workingtree())
 
300
        out, err = self.run_bzr(['annotate', 'empty'])
 
301
        self.assertEqual('', out)
 
302
 
 
303
    def test_annotate_directory(self):
 
304
        """Test --directory option"""
 
305
        wt = self.make_branch_and_tree('a')
 
306
        self.build_tree_contents([('a/hello.txt', 'my helicopter\n')])
 
307
        wt.add(['hello.txt'])
 
308
        wt.commit('commit', committer='test@user')
 
309
        out, err = self.run_bzr(['annotate', '-d', 'a', 'hello.txt'])
 
310
        self.assertEqualDiff('1   test@us | my helicopter\n', out)
 
311
 
 
312
 
 
313
class TestSmartServerAnnotate(tests.TestCaseWithTransport):
 
314
 
 
315
    def test_simple_annotate(self):
 
316
        self.setup_smart_server_with_call_log()
 
317
        wt = self.make_branch_and_tree('branch')
 
318
        self.build_tree_contents([('branch/hello.txt', 'my helicopter\n')])
 
319
        wt.add(['hello.txt'])
 
320
        wt.commit('commit', committer='test@user')
 
321
        self.reset_smart_call_log()
 
322
        out, err = self.run_bzr(['annotate', "-d", self.get_url('branch'),
 
323
            "hello.txt"])
 
324
        # This figure represent the amount of work to perform this use case. It
 
325
        # is entirely ok to reduce this number if a test fails due to rpc_count
 
326
        # being too low. If rpc_count increases, more network roundtrips have
 
327
        # become necessary for this use case. Please do not adjust this number
 
328
        # upwards without agreement from bzr's network support maintainers.
 
329
        self.assertLength(16, self.hpss_calls)
 
330
        self.assertLength(1, self.hpss_connections)
 
331
        self.expectFailure("annotate accesses inventories, which require VFS access",
 
332
            self.assertThat, self.hpss_calls, ContainsNoVfsCalls)