~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: Martin Pool
  • Date: 2005-05-17 06:56:16 UTC
  • Revision ID: mbp@sourcefrog.net-20050517065616-6f23381d6184a8aa
- add space for un-merged patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
# -*- coding: utf-8 -*-
3
 
# vim: encoding=utf-8
4
 
#
5
 
# This program is free software; you can redistribute it and/or modify
6
 
# it under the terms of the GNU General Public License as published by
7
 
# the Free Software Foundation; either version 2 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# This program is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
# GNU General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU General Public License
16
 
# along with this program; if not, write to the Free Software
17
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 
19
 
import os
20
 
from cStringIO import StringIO
21
 
 
22
 
from bzrlib.tests import BzrTestBase, TestCaseWithTransport
23
 
from bzrlib.log import (LogFormatter, show_log, LongLogFormatter,
24
 
                        ShortLogFormatter, LineLogFormatter)
25
 
from bzrlib.branch import Branch
26
 
from bzrlib.errors import InvalidRevisionNumber
27
 
 
28
 
 
29
 
class _LogEntry(object):
30
 
    # should probably move into bzrlib.log?
31
 
    pass
32
 
 
33
 
 
34
 
class LogCatcher(LogFormatter):
35
 
    """Pull log messages into list rather than displaying them.
36
 
 
37
 
    For ease of testing we save log messages here rather than actually
38
 
    formatting them, so that we can precisely check the result without
39
 
    being too dependent on the exact formatting.
40
 
 
41
 
    We should also test the LogFormatter.
42
 
    """
43
 
    def __init__(self):
44
 
        super(LogCatcher, self).__init__(to_file=None)
45
 
        self.logs = []
46
 
 
47
 
    def show(self, revno, rev, delta):
48
 
        le = _LogEntry()
49
 
        le.revno = revno
50
 
        le.rev = rev
51
 
        le.delta = delta
52
 
        self.logs.append(le)
53
 
 
54
 
 
55
 
class SimpleLogTest(TestCaseWithTransport):
56
 
 
57
 
    def checkDelta(self, delta, **kw):
58
 
        """Check the filenames touched by a delta are as expected."""
59
 
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
60
 
            expected = kw.get(n, [])
61
 
 
62
 
            # tests are written with unix paths; fix them up for windows
63
 
            #if os.sep != '/':
64
 
            #    expected = [x.replace('/', os.sep) for x in expected]
65
 
 
66
 
            # strip out only the path components
67
 
            got = [x[0] for x in getattr(delta, n)]
68
 
            self.assertEquals(expected, got)
69
 
 
70
 
    def test_cur_revno(self):
71
 
        wt = self.make_branch_and_tree('.')
72
 
        b = wt.branch
73
 
 
74
 
        lf = LogCatcher()
75
 
        wt.commit('empty commit')
76
 
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
77
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
78
 
                          start_revision=2, end_revision=1) 
79
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
80
 
                          start_revision=1, end_revision=2) 
81
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
82
 
                          start_revision=0, end_revision=2) 
83
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
84
 
                          start_revision=1, end_revision=0) 
85
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
86
 
                          start_revision=-1, end_revision=1) 
87
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
88
 
                          start_revision=1, end_revision=-1) 
89
 
 
90
 
    def test_cur_revno(self):
91
 
        wt = self.make_branch_and_tree('.')
92
 
        b = wt.branch
93
 
 
94
 
        lf = LogCatcher()
95
 
        wt.commit('empty commit')
96
 
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
97
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
98
 
                          start_revision=2, end_revision=1) 
99
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
100
 
                          start_revision=1, end_revision=2) 
101
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
102
 
                          start_revision=0, end_revision=2) 
103
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
104
 
                          start_revision=1, end_revision=0) 
105
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
106
 
                          start_revision=-1, end_revision=1) 
107
 
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
108
 
                          start_revision=1, end_revision=-1) 
109
 
 
110
 
    def test_simple_log(self):
111
 
        eq = self.assertEquals
112
 
        
113
 
        wt = self.make_branch_and_tree('.')
114
 
        b = wt.branch
115
 
 
116
 
        lf = LogCatcher()
117
 
        show_log(b, lf)
118
 
        # no entries yet
119
 
        eq(lf.logs, [])
120
 
 
121
 
        wt.commit('empty commit')
122
 
        lf = LogCatcher()
123
 
        show_log(b, lf, verbose=True)
124
 
        eq(len(lf.logs), 1)
125
 
        eq(lf.logs[0].revno, 1)
126
 
        eq(lf.logs[0].rev.message, 'empty commit')
127
 
        d = lf.logs[0].delta
128
 
        self.log('log delta: %r' % d)
129
 
        self.checkDelta(d)
130
 
 
131
 
        self.build_tree(['hello'])
132
 
        wt.add('hello')
133
 
        wt.commit('add one file')
134
 
 
135
 
        lf = StringIO()
136
 
        # log using regular thing
137
 
        show_log(b, LongLogFormatter(lf))
138
 
        lf.seek(0)
139
 
        for l in lf.readlines():
140
 
            self.log(l)
141
 
 
142
 
        # get log as data structure
143
 
        lf = LogCatcher()
144
 
        show_log(b, lf, verbose=True)
145
 
        eq(len(lf.logs), 2)
146
 
        self.log('log entries:')
147
 
        for logentry in lf.logs:
148
 
            self.log('%4d %s' % (logentry.revno, logentry.rev.message))
149
 
        
150
 
        # first one is most recent
151
 
        logentry = lf.logs[0]
152
 
        eq(logentry.revno, 2)
153
 
        eq(logentry.rev.message, 'add one file')
154
 
        d = logentry.delta
155
 
        self.log('log 2 delta: %r' % d)
156
 
        # self.checkDelta(d, added=['hello'])
157
 
        
158
 
        # commit a log message with control characters
159
 
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
160
 
        self.log("original commit message: %r", msg)
161
 
        wt.commit(msg)
162
 
        lf = LogCatcher()
163
 
        show_log(b, lf, verbose=True)
164
 
        committed_msg = lf.logs[0].rev.message
165
 
        self.log("escaped commit message: %r", committed_msg)
166
 
        self.assert_(msg != committed_msg)
167
 
        self.assert_(len(committed_msg) > len(msg))
168
 
 
169
 
        # Check that log message with only XML-valid characters isn't
170
 
        # escaped.  As ElementTree apparently does some kind of
171
 
        # newline conversion, neither LF (\x0A) nor CR (\x0D) are
172
 
        # included in the test commit message, even though they are
173
 
        # valid XML 1.0 characters.
174
 
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
175
 
        self.log("original commit message: %r", msg)
176
 
        wt.commit(msg)
177
 
        lf = LogCatcher()
178
 
        show_log(b, lf, verbose=True)
179
 
        committed_msg = lf.logs[0].rev.message
180
 
        self.log("escaped commit message: %r", committed_msg)
181
 
        self.assert_(msg == committed_msg)
182
 
 
183
 
    def test_trailing_newlines(self):
184
 
        wt = self.make_branch_and_tree('.')
185
 
        b = wt.branch
186
 
        b.nick='test'
187
 
        open('a', 'wb').write('hello moto\n')
188
 
        wt.add('a')
189
 
        wt.commit('simple log message', rev_id='a1'
190
 
                , timestamp=1132586655.459960938, timezone=-6*3600
191
 
                , committer='Joe Foo <joe@foo.com>')
192
 
        open('b', 'wb').write('goodbye\n')
193
 
        wt.add('b')
194
 
        wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
195
 
                , timestamp=1132586842.411175966, timezone=-6*3600
196
 
                , committer='Joe Foo <joe@foo.com>')
197
 
 
198
 
        open('c', 'wb').write('just another manic monday\n')
199
 
        wt.add('c')
200
 
        wt.commit('single line with trailing newline\n', rev_id='a3'
201
 
                , timestamp=1132587176.835228920, timezone=-6*3600
202
 
                , committer = 'Joe Foo <joe@foo.com>')
203
 
 
204
 
        sio = StringIO()
205
 
        lf = ShortLogFormatter(to_file=sio)
206
 
        show_log(b, lf)
207
 
        self.assertEquals(sio.getvalue(), """\
208
 
    3 Joe Foo\t2005-11-21
209
 
      single line with trailing newline
210
 
 
211
 
    2 Joe Foo\t2005-11-21
212
 
      multiline
213
 
      log
214
 
      message
215
 
 
216
 
    1 Joe Foo\t2005-11-21
217
 
      simple log message
218
 
 
219
 
""")
220
 
 
221
 
        sio = StringIO()
222
 
        lf = LongLogFormatter(to_file=sio)
223
 
        show_log(b, lf)
224
 
        self.assertEquals(sio.getvalue(), """\
225
 
------------------------------------------------------------
226
 
revno: 3
227
 
committer: Joe Foo <joe@foo.com>
228
 
branch nick: test
229
 
timestamp: Mon 2005-11-21 09:32:56 -0600
230
 
message:
231
 
  single line with trailing newline
232
 
------------------------------------------------------------
233
 
revno: 2
234
 
committer: Joe Foo <joe@foo.com>
235
 
branch nick: test
236
 
timestamp: Mon 2005-11-21 09:27:22 -0600
237
 
message:
238
 
  multiline
239
 
  log
240
 
  message
241
 
------------------------------------------------------------
242
 
revno: 1
243
 
committer: Joe Foo <joe@foo.com>
244
 
branch nick: test
245
 
timestamp: Mon 2005-11-21 09:24:15 -0600
246
 
message:
247
 
  simple log message
248
 
""")
249
 
        
250
 
    def test_verbose_log(self):
251
 
        """Verbose log includes changed files
252
 
        
253
 
        bug #4676
254
 
        """
255
 
        wt = self.make_branch_and_tree('.')
256
 
        b = wt.branch
257
 
        self.build_tree(['a'])
258
 
        wt.add('a')
259
 
        # XXX: why does a longer nick show up?
260
 
        b.nick = 'test_verbose_log'
261
 
        wt.commit(message='add a', 
262
 
                  timestamp=1132711707, 
263
 
                  timezone=36000,
264
 
                  committer='Lorem Ipsum <test@example.com>')
265
 
        logfile = file('out.tmp', 'w+')
266
 
        formatter = LongLogFormatter(to_file=logfile)
267
 
        show_log(b, formatter, verbose=True)
268
 
        logfile.flush()
269
 
        logfile.seek(0)
270
 
        log_contents = logfile.read()
271
 
        self.assertEqualDiff(log_contents, '''\
272
 
------------------------------------------------------------
273
 
revno: 1
274
 
committer: Lorem Ipsum <test@example.com>
275
 
branch nick: test_verbose_log
276
 
timestamp: Wed 2005-11-23 12:08:27 +1000
277
 
message:
278
 
  add a
279
 
added:
280
 
  a
281
 
''')
282
 
 
283
 
    def test_line_log(self):
284
 
        """Line log should show revno
285
 
        
286
 
        bug #5162
287
 
        """
288
 
        wt = self.make_branch_and_tree('.')
289
 
        b = wt.branch
290
 
        self.build_tree(['a'])
291
 
        wt.add('a')
292
 
        b.nick = 'test-line-log'
293
 
        wt.commit(message='add a', 
294
 
                  timestamp=1132711707, 
295
 
                  timezone=36000,
296
 
                  committer='Line-Log-Formatter Tester <test@line.log>')
297
 
        logfile = file('out.tmp', 'w+')
298
 
        formatter = LineLogFormatter(to_file=logfile)
299
 
        show_log(b, formatter)
300
 
        logfile.flush()
301
 
        logfile.seek(0)
302
 
        log_contents = logfile.read()
303
 
        self.assertEqualDiff(log_contents, '1: Line-Log-Formatte... 2005-11-23 add a\n')