~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/selftest/testlog.py

  • Committer: Martin Pool
  • Date: 2005-09-30 05:56:05 UTC
  • mto: (1185.14.2)
  • mto: This revision was merged to the branch mainline in revision 1396.
  • Revision ID: mbp@sourcefrog.net-20050930055605-a2c534529b392a7d
- fix upgrade for transport changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
2
 
# -*- coding: utf-8 -*-
3
 
# vim: encoding=utf-8
4
 
#
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
 
5
3
# This program is free software; you can redistribute it and/or modify
6
4
# it under the terms of the GNU General Public License as published by
7
5
# the Free Software Foundation; either version 2 of the License, or
8
6
# (at your option) any later version.
9
 
#
 
7
 
10
8
# This program is distributed in the hope that it will be useful,
11
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
11
# GNU General Public License for more details.
14
 
#
 
12
 
15
13
# You should have received a copy of the GNU General Public License
16
14
# along with this program; if not, write to the Free Software
17
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
17
import os
20
18
from cStringIO import StringIO
21
19
 
22
 
from bzrlib.tests import BzrTestBase, TestCaseWithTransport
23
 
from bzrlib.log import (show_log, 
24
 
                        get_view_revisions, 
25
 
                        LogFormatter, 
26
 
                        LongLogFormatter, 
27
 
                        ShortLogFormatter, 
28
 
                        LineLogFormatter)
 
20
from bzrlib.selftest import BzrTestBase, TestCaseInTempDir
 
21
from bzrlib.log import LogFormatter, show_log, LongLogFormatter
29
22
from bzrlib.branch import Branch
30
23
from bzrlib.errors import InvalidRevisionNumber
31
24
 
32
 
 
33
25
class _LogEntry(object):
34
26
    # should probably move into bzrlib.log?
35
27
    pass
47
39
    def __init__(self):
48
40
        super(LogCatcher, self).__init__(to_file=None)
49
41
        self.logs = []
50
 
 
 
42
        
 
43
        
51
44
    def show(self, revno, rev, delta):
52
45
        le = _LogEntry()
53
46
        le.revno = revno
56
49
        self.logs.append(le)
57
50
 
58
51
 
59
 
class SimpleLogTest(TestCaseWithTransport):
 
52
class SimpleLogTest(TestCaseInTempDir):
60
53
 
61
54
    def checkDelta(self, delta, **kw):
62
55
        """Check the filenames touched by a delta are as expected."""
64
57
            expected = kw.get(n, [])
65
58
 
66
59
            # tests are written with unix paths; fix them up for windows
67
 
            #if os.sep != '/':
68
 
            #    expected = [x.replace('/', os.sep) for x in expected]
 
60
            if os.sep != '/':
 
61
                expected = [x.replace('/', os.sep) for x in expected]
69
62
 
70
63
            # strip out only the path components
71
64
            got = [x[0] for x in getattr(delta, n)]
72
65
            self.assertEquals(expected, got)
73
66
 
74
67
    def test_cur_revno(self):
75
 
        wt = self.make_branch_and_tree('.')
76
 
        b = wt.branch
 
68
        b = Branch.initialize('.')
77
69
 
78
70
        lf = LogCatcher()
79
 
        wt.commit('empty commit')
 
71
        b.commit('empty commit')
80
72
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
81
73
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
82
74
                          start_revision=2, end_revision=1) 
94
86
    def test_simple_log(self):
95
87
        eq = self.assertEquals
96
88
        
97
 
        wt = self.make_branch_and_tree('.')
98
 
        b = wt.branch
 
89
        b = Branch.initialize('.')
99
90
 
100
91
        lf = LogCatcher()
101
92
        show_log(b, lf)
102
93
        # no entries yet
103
94
        eq(lf.logs, [])
104
95
 
105
 
        wt.commit('empty commit')
 
96
 
 
97
        b.commit('empty commit')
106
98
        lf = LogCatcher()
107
99
        show_log(b, lf, verbose=True)
108
100
        eq(len(lf.logs), 1)
109
 
        eq(lf.logs[0].revno, '1')
 
101
        eq(lf.logs[0].revno, 1)
110
102
        eq(lf.logs[0].rev.message, 'empty commit')
111
103
        d = lf.logs[0].delta
112
104
        self.log('log delta: %r' % d)
113
105
        self.checkDelta(d)
114
106
 
 
107
 
115
108
        self.build_tree(['hello'])
116
 
        wt.add('hello')
117
 
        wt.commit('add one file')
 
109
        b.add('hello')
 
110
        b.commit('add one file')
118
111
 
119
112
        lf = StringIO()
120
113
        # log using regular thing
129
122
        eq(len(lf.logs), 2)
130
123
        self.log('log entries:')
131
124
        for logentry in lf.logs:
132
 
            self.log('%4s %s' % (logentry.revno, logentry.rev.message))
 
125
            self.log('%4d %s' % (logentry.revno, logentry.rev.message))
133
126
        
134
127
        # first one is most recent
135
128
        logentry = lf.logs[0]
136
 
        eq(logentry.revno, '2')
 
129
        eq(logentry.revno, 2)
137
130
        eq(logentry.rev.message, 'add one file')
138
131
        d = logentry.delta
139
132
        self.log('log 2 delta: %r' % d)
141
134
        
142
135
        # commit a log message with control characters
143
136
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
144
 
        self.log("original commit message: %r", msg)
145
 
        wt.commit(msg)
 
137
        b.commit(msg)
146
138
        lf = LogCatcher()
147
139
        show_log(b, lf, verbose=True)
148
140
        committed_msg = lf.logs[0].rev.message
149
141
        self.log("escaped commit message: %r", committed_msg)
150
142
        self.assert_(msg != committed_msg)
151
143
        self.assert_(len(committed_msg) > len(msg))
152
 
 
153
 
        # Check that log message with only XML-valid characters isn't
154
 
        # escaped.  As ElementTree apparently does some kind of
155
 
        # newline conversion, neither LF (\x0A) nor CR (\x0D) are
156
 
        # included in the test commit message, even though they are
157
 
        # valid XML 1.0 characters.
158
 
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
159
 
        self.log("original commit message: %r", msg)
160
 
        wt.commit(msg)
161
 
        lf = LogCatcher()
162
 
        show_log(b, lf, verbose=True)
163
 
        committed_msg = lf.logs[0].rev.message
164
 
        self.log("escaped commit message: %r", committed_msg)
165
 
        self.assert_(msg == committed_msg)
166
 
 
167
 
    def test_trailing_newlines(self):
168
 
        wt = self.make_branch_and_tree('.')
169
 
        b = wt.branch
170
 
        b.nick='test'
171
 
        open('a', 'wb').write('hello moto\n')
172
 
        wt.add('a')
173
 
        wt.commit('simple log message', rev_id='a1'
174
 
                , timestamp=1132586655.459960938, timezone=-6*3600
175
 
                , committer='Joe Foo <joe@foo.com>')
176
 
        open('b', 'wb').write('goodbye\n')
177
 
        wt.add('b')
178
 
        wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
179
 
                , timestamp=1132586842.411175966, timezone=-6*3600
180
 
                , committer='Joe Foo <joe@foo.com>')
181
 
 
182
 
        open('c', 'wb').write('just another manic monday\n')
183
 
        wt.add('c')
184
 
        wt.commit('single line with trailing newline\n', rev_id='a3'
185
 
                , timestamp=1132587176.835228920, timezone=-6*3600
186
 
                , committer = 'Joe Foo <joe@foo.com>')
187
 
 
188
 
        sio = StringIO()
189
 
        lf = ShortLogFormatter(to_file=sio)
190
 
        show_log(b, lf)
191
 
        self.assertEquals(sio.getvalue(), """\
192
 
    3 Joe Foo\t2005-11-21
193
 
      single line with trailing newline
194
 
 
195
 
    2 Joe Foo\t2005-11-21
196
 
      multiline
197
 
      log
198
 
      message
199
 
 
200
 
    1 Joe Foo\t2005-11-21
201
 
      simple log message
202
 
 
203
 
""")
204
 
 
205
 
        sio = StringIO()
206
 
        lf = LongLogFormatter(to_file=sio)
207
 
        show_log(b, lf)
208
 
        self.assertEquals(sio.getvalue(), """\
209
 
------------------------------------------------------------
210
 
revno: 3
211
 
committer: Joe Foo <joe@foo.com>
212
 
branch nick: test
213
 
timestamp: Mon 2005-11-21 09:32:56 -0600
214
 
message:
215
 
  single line with trailing newline
216
 
------------------------------------------------------------
217
 
revno: 2
218
 
committer: Joe Foo <joe@foo.com>
219
 
branch nick: test
220
 
timestamp: Mon 2005-11-21 09:27:22 -0600
221
 
message:
222
 
  multiline
223
 
  log
224
 
  message
225
 
------------------------------------------------------------
226
 
revno: 1
227
 
committer: Joe Foo <joe@foo.com>
228
 
branch nick: test
229
 
timestamp: Mon 2005-11-21 09:24:15 -0600
230
 
message:
231
 
  simple log message
232
 
""")
233
 
        
234
 
    def test_verbose_log(self):
235
 
        """Verbose log includes changed files
236
 
        
237
 
        bug #4676
238
 
        """
239
 
        wt = self.make_branch_and_tree('.')
240
 
        b = wt.branch
241
 
        self.build_tree(['a'])
242
 
        wt.add('a')
243
 
        # XXX: why does a longer nick show up?
244
 
        b.nick = 'test_verbose_log'
245
 
        wt.commit(message='add a', 
246
 
                  timestamp=1132711707, 
247
 
                  timezone=36000,
248
 
                  committer='Lorem Ipsum <test@example.com>')
249
 
        logfile = file('out.tmp', 'w+')
250
 
        formatter = LongLogFormatter(to_file=logfile)
251
 
        show_log(b, formatter, verbose=True)
252
 
        logfile.flush()
253
 
        logfile.seek(0)
254
 
        log_contents = logfile.read()
255
 
        self.assertEqualDiff(log_contents, '''\
256
 
------------------------------------------------------------
257
 
revno: 1
258
 
committer: Lorem Ipsum <test@example.com>
259
 
branch nick: test_verbose_log
260
 
timestamp: Wed 2005-11-23 12:08:27 +1000
261
 
message:
262
 
  add a
263
 
added:
264
 
  a
265
 
''')
266
 
 
267
 
    def test_line_log(self):
268
 
        """Line log should show revno
269
 
        
270
 
        bug #5162
271
 
        """
272
 
        wt = self.make_branch_and_tree('.')
273
 
        b = wt.branch
274
 
        self.build_tree(['a'])
275
 
        wt.add('a')
276
 
        b.nick = 'test-line-log'
277
 
        wt.commit(message='add a', 
278
 
                  timestamp=1132711707, 
279
 
                  timezone=36000,
280
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
281
 
        logfile = file('out.tmp', 'w+')
282
 
        formatter = LineLogFormatter(to_file=logfile)
283
 
        show_log(b, formatter)
284
 
        logfile.flush()
285
 
        logfile.seek(0)
286
 
        log_contents = logfile.read()
287
 
        self.assertEqualDiff(log_contents, '1: Line-Log-Formatte... 2005-11-23 add a\n')
288
 
 
289
 
    def make_tree_with_commits(self):
290
 
        """Create a tree with well-known revision ids"""
291
 
        wt = self.make_branch_and_tree('tree1')
292
 
        wt.commit('commit one', rev_id='1')
293
 
        wt.commit('commit two', rev_id='2')
294
 
        wt.commit('commit three', rev_id='3')
295
 
        mainline_revs = [None, '1', '2', '3']
296
 
        rev_nos = {'1': 1, '2': 2, '3': 3}
297
 
        return mainline_revs, rev_nos, wt
298
 
 
299
 
    def make_tree_with_merges(self):
300
 
        """Create a tree with well-known revision ids and a merge"""
301
 
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
302
 
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
303
 
        tree2.commit('four-a', rev_id='4a')
304
 
        wt.merge_from_branch(tree2.branch)
305
 
        wt.commit('four-b', rev_id='4b')
306
 
        mainline_revs.append('4b')
307
 
        rev_nos['4b'] = 4
308
 
        # 4a: 3.1.1
309
 
        return mainline_revs, rev_nos, wt
310
 
 
311
 
    def make_tree_with_many_merges(self):
312
 
        """Create a tree with well-known revision ids"""
313
 
        wt = self.make_branch_and_tree('tree1')
314
 
        wt.commit('commit one', rev_id='1')
315
 
        wt.commit('commit two', rev_id='2')
316
 
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
317
 
        tree3.commit('commit three a', rev_id='3a')
318
 
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
319
 
        tree2.merge_from_branch(tree3.branch)
320
 
        tree2.commit('commit three b', rev_id='3b')
321
 
        wt.merge_from_branch(tree2.branch)
322
 
        wt.commit('commit three c', rev_id='3c')
323
 
        tree2.commit('four-a', rev_id='4a')
324
 
        wt.merge_from_branch(tree2.branch)
325
 
        wt.commit('four-b', rev_id='4b')
326
 
        mainline_revs = [None, '1', '2', '3c', '4b']
327
 
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
328
 
        full_rev_nos_for_reference = {
329
 
            '1': '1',
330
 
            '2': '2',
331
 
            '3a': '2.2.1', #first commit tree 3
332
 
            '3b': '2.1.1', # first commit tree 2
333
 
            '3c': '3', #merges 3b to main
334
 
            '4a': '2.1.2', # second commit tree 2
335
 
            '4b': '4', # merges 4a to main
336
 
            }
337
 
        return mainline_revs, rev_nos, wt
338
 
 
339
 
    def test_get_view_revisions_forward(self):
340
 
        """Test the get_view_revisions method"""
341
 
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
342
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
343
 
                                            'forward'))
344
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
345
 
            revisions)
346
 
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
347
 
                                             'forward', include_merges=False))
348
 
        self.assertEqual(revisions, revisions2)
349
 
 
350
 
    def test_get_view_revisions_reverse(self):
351
 
        """Test the get_view_revisions with reverse"""
352
 
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
353
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
354
 
                                            'reverse'))
355
 
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
356
 
            revisions)
357
 
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
358
 
                                             'reverse', include_merges=False))
359
 
        self.assertEqual(revisions, revisions2)
360
 
 
361
 
    def test_get_view_revisions_merge(self):
362
 
        """Test get_view_revisions when there are merges"""
363
 
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
364
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
365
 
                                            'forward'))
366
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
367
 
            ('4b', '4', 0), ('4a', '3.1.1', 1)],
368
 
            revisions)
369
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
370
 
                                             'forward', include_merges=False))
371
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
372
 
            ('4b', '4', 0)],
373
 
            revisions)
374
 
 
375
 
    def test_get_view_revisions_merge_reverse(self):
376
 
        """Test get_view_revisions in reverse when there are merges"""
377
 
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
378
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
379
 
                                            'reverse'))
380
 
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
381
 
            ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
382
 
            revisions)
383
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
384
 
                                             'reverse', include_merges=False))
385
 
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
386
 
            ('1', '1', 0)],
387
 
            revisions)
388
 
 
389
 
    def test_get_view_revisions_merge2(self):
390
 
        """Test get_view_revisions when there are merges"""
391
 
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
392
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
393
 
                                            'forward'))
394
 
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
395
 
            ('3a', '2.2.1', 1), ('3b', '2.1.1', 1), ('4b', '4', 0),
396
 
            ('4a', '2.1.2', 1)]
397
 
        self.assertEqual(expected, revisions)
398
 
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
399
 
                                             'forward', include_merges=False))
400
 
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
401
 
            ('4b', '4', 0)],
402
 
            revisions)