~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_log.py

  • Committer: Robert Collins
  • Date: 2006-06-16 15:59:24 UTC
  • mto: (1780.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 1781.
  • Revision ID: robertc@robertcollins.net-20060616155924-b8a6591d32f8ab20
New corner case from John Meinel, showing up the need to check the directory lexographically outside of a single tree's root. Fixed.

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')