/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1685.1.80 by Wouter van Heyst
more code cleanup
2
#
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1685.1.80 by Wouter van Heyst
more code cleanup
7
#
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1685.1.80 by Wouter van Heyst
more code cleanup
12
#
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
13
# You should have received a copy of the GNU General Public License
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
16
17
import os
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
18
from cStringIO import StringIO
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
19
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
20
from bzrlib import log
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
21
from bzrlib.tests import TestCase, TestCaseWithTransport
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
22
from bzrlib.log import (show_log,
23
                        get_view_revisions,
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
24
                        LogRevision,
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
25
                        LogFormatter,
26
                        LongLogFormatter,
27
                        ShortLogFormatter,
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
28
                        LineLogFormatter)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
29
from bzrlib.branch import Branch
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
30
from bzrlib.errors import (
31
    BzrCommandError,
32
    InvalidRevisionNumber,
33
    )
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
34
from bzrlib.revision import Revision
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
35
from bzrlib.revisionspec import (
36
    RevisionInfo,
37
    RevisionSpec,
38
    )
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
39
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
40
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
41
class LogCatcher(LogFormatter):
42
    """Pull log messages into list rather than displaying them.
43
44
    For ease of testing we save log messages here rather than actually
45
    formatting them, so that we can precisely check the result without
46
    being too dependent on the exact formatting.
47
48
    We should also test the LogFormatter.
49
    """
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
50
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
51
    supports_delta = True
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
52
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
53
    def __init__(self):
54
        super(LogCatcher, self).__init__(to_file=None)
55
        self.logs = []
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
56
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
57
    def log_revision(self, revision):
58
        self.logs.append(revision)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
59
60
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
61
class TestShowLog(TestCaseWithTransport):
1102 by Martin Pool
- merge test refactoring from robertc
62
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
63
    def checkDelta(self, delta, **kw):
64
        """Check the filenames touched by a delta are as expected."""
65
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
66
            expected = kw.get(n, [])
67
            # strip out only the path components
68
            got = [x[0] for x in getattr(delta, n)]
69
            self.assertEquals(expected, got)
70
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
71
    def test_cur_revno(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
72
        wt = self.make_branch_and_tree('.')
73
        b = wt.branch
1092.3.4 by Robert Collins
update symlink branch to integration
74
75
        lf = LogCatcher()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
76
        wt.commit('empty commit')
1092.3.4 by Robert Collins
update symlink branch to integration
77
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
78
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
79
                          start_revision=2, end_revision=1) 
80
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
81
                          start_revision=1, end_revision=2) 
82
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
83
                          start_revision=0, end_revision=2) 
84
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
85
                          start_revision=1, end_revision=0) 
86
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
87
                          start_revision=-1, end_revision=1) 
88
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
89
                          start_revision=1, end_revision=-1) 
90
1102 by Martin Pool
- merge test refactoring from robertc
91
    def test_simple_log(self):
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
92
        eq = self.assertEquals
93
        
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
94
        wt = self.make_branch_and_tree('.')
95
        b = wt.branch
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
96
97
        lf = LogCatcher()
98
        show_log(b, lf)
99
        # no entries yet
100
        eq(lf.logs, [])
101
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
102
        wt.commit('empty commit')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
103
        lf = LogCatcher()
104
        show_log(b, lf, verbose=True)
105
        eq(len(lf.logs), 1)
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
106
        eq(lf.logs[0].revno, '1')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
107
        eq(lf.logs[0].rev.message, 'empty commit')
108
        d = lf.logs[0].delta
109
        self.log('log delta: %r' % d)
110
        self.checkDelta(d)
111
112
        self.build_tree(['hello'])
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
113
        wt.add('hello')
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
114
        wt.commit('add one file',
115
                  committer=u'\u013d\xf3r\xe9m \xcdp\u0161\xfam '
116
                            u'<test@example.com>')
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
117
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
118
        lf = self.make_utf8_encoded_stringio()
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
119
        # log using regular thing
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
120
        show_log(b, LongLogFormatter(lf))
121
        lf.seek(0)
122
        for l in lf.readlines():
123
            self.log(l)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
124
125
        # get log as data structure
126
        lf = LogCatcher()
127
        show_log(b, lf, verbose=True)
128
        eq(len(lf.logs), 2)
129
        self.log('log entries:')
130
        for logentry in lf.logs:
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
131
            self.log('%4s %s' % (logentry.revno, logentry.rev.message))
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
132
        
133
        # first one is most recent
134
        logentry = lf.logs[0]
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
135
        eq(logentry.revno, '2')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
136
        eq(logentry.rev.message, 'add one file')
137
        d = logentry.delta
138
        self.log('log 2 delta: %r' % d)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
139
        self.checkDelta(d, added=['hello'])
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
140
        
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
141
        # commit a log message with control characters
142
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
143
        self.log("original commit message: %r", msg)
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
144
        wt.commit(msg)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
145
        lf = LogCatcher()
146
        show_log(b, lf, verbose=True)
147
        committed_msg = lf.logs[0].rev.message
148
        self.log("escaped commit message: %r", committed_msg)
149
        self.assert_(msg != committed_msg)
150
        self.assert_(len(committed_msg) > len(msg))
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
151
152
        # Check that log message with only XML-valid characters isn't
153
        # escaped.  As ElementTree apparently does some kind of
154
        # newline conversion, neither LF (\x0A) nor CR (\x0D) are
155
        # included in the test commit message, even though they are
156
        # valid XML 1.0 characters.
157
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
158
        self.log("original commit message: %r", msg)
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
159
        wt.commit(msg)
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
160
        lf = LogCatcher()
161
        show_log(b, lf, verbose=True)
162
        committed_msg = lf.logs[0].rev.message
163
        self.log("escaped commit message: %r", committed_msg)
164
        self.assert_(msg == committed_msg)
1185.31.22 by John Arbash Meinel
[merge] bzr.dev
165
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
166
    def test_deltas_in_merge_revisions(self):
167
        """Check deltas created for both mainline and merge revisions"""
168
        eq = self.assertEquals
169
        wt = self.make_branch_and_tree('parent')
170
        self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
171
        wt.add('file1')
172
        wt.add('file2')
173
        wt.commit(message='add file1 and file2')
2581.1.6 by Martin Pool
fix up more run_bzr callers
174
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
175
        os.unlink('child/file1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
176
        file('child/file2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
177
        self.run_bzr(['commit', '-m', 'remove file1 and modify file2',
178
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
179
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
180
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
181
        wt.commit('merge child branch')
182
        os.chdir('..')
183
        b = wt.branch
184
        lf = LogCatcher()
185
        lf.supports_merge_revisions = True
186
        show_log(b, lf, verbose=True)
187
        eq(len(lf.logs),3)
188
        logentry = lf.logs[0]
189
        eq(logentry.revno, '2')
190
        eq(logentry.rev.message, 'merge child branch')
191
        d = logentry.delta
192
        self.checkDelta(d, removed=['file1'], modified=['file2'])
193
        logentry = lf.logs[1]
194
        eq(logentry.revno, '1.1.1')
195
        eq(logentry.rev.message, 'remove file1 and modify file2')
196
        d = logentry.delta
197
        self.checkDelta(d, removed=['file1'], modified=['file2'])
198
        logentry = lf.logs[2]
199
        eq(logentry.revno, '1')
200
        eq(logentry.rev.message, 'add file1 and file2')
201
        d = logentry.delta
202
        self.checkDelta(d, added=['file1', 'file2'])
203
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
204
    def test_merges_nonsupporting_formatter(self):
205
        """Tests that show_log will raise if the formatter doesn't
206
        support merge revisions."""
207
        wt = self.make_branch_and_memory_tree('.')
208
        wt.lock_write()
209
        try:
210
            wt.add('')
211
            wt.commit('rev-1', rev_id='rev-1',
212
                      timestamp=1132586655, timezone=36000,
213
                      committer='Joe Foo <joe@foo.com>')
214
            wt.commit('rev-merged', rev_id='rev-2a',
215
                      timestamp=1132586700, timezone=36000,
216
                      committer='Joe Foo <joe@foo.com>')
217
            wt.set_parent_ids(['rev-1', 'rev-2a'])
218
            wt.branch.set_last_revision_info(1, 'rev-1')
219
            wt.commit('rev-2', rev_id='rev-2b',
220
                      timestamp=1132586800, timezone=36000,
221
                      committer='Joe Foo <joe@foo.com>')
222
            logfile = self.make_utf8_encoded_stringio()
223
            formatter = ShortLogFormatter(to_file=logfile)
224
            wtb = wt.branch
225
            lf = LogCatcher()
226
            revspec = RevisionSpec.from_string('1.1.1')
227
            rev = revspec.in_history(wtb)
228
            self.assertRaises(BzrCommandError, show_log, wtb, lf,
229
                              start_revision=rev, end_revision=rev)
230
        finally:
231
            wt.unlock()
232
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
233
234
def make_commits_with_trailing_newlines(wt):
235
    """Helper method for LogFormatter tests"""    
236
    b = wt.branch
237
    b.nick='test'
238
    open('a', 'wb').write('hello moto\n')
239
    wt.add('a')
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
240
    wt.commit('simple log message', rev_id='a1',
241
              timestamp=1132586655.459960938, timezone=-6*3600,
242
              committer='Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
243
    open('b', 'wb').write('goodbye\n')
244
    wt.add('b')
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
245
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
246
              timestamp=1132586842.411175966, timezone=-6*3600,
247
              committer='Joe Foo <joe@foo.com>',
248
              author='Joe Bar <joe@bar.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
249
250
    open('c', 'wb').write('just another manic monday\n')
251
    wt.add('c')
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
252
    wt.commit('single line with trailing newline\n', rev_id='a3',
253
              timestamp=1132587176.835228920, timezone=-6*3600,
254
              committer = 'Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
255
    return b
256
257
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
258
def normalize_log(log):
259
    """Replaces the variable lines of logs with fixed lines"""
260
    author = 'author: Dolor Sit <test@example.com>'
261
    committer = 'committer: Lorem Ipsum <test@example.com>'
262
    lines = log.splitlines(True)
263
    for idx,line in enumerate(lines):
264
        stripped_line = line.lstrip()
265
        indent = ' ' * (len(line) - len(stripped_line))
266
        if stripped_line.startswith('author:'):
267
            lines[idx] = indent + author + '\n'
268
        elif stripped_line.startswith('committer:'):
269
            lines[idx] = indent + committer + '\n'
270
        elif stripped_line.startswith('timestamp:'):
271
            lines[idx] = indent + 'timestamp: Just now\n'
272
    return ''.join(lines)
273
274
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
275
class TestShortLogFormatter(TestCaseWithTransport):
276
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
277
    def test_trailing_newlines(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
278
        wt = self.make_branch_and_tree('.')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
279
        b = make_commits_with_trailing_newlines(wt)
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
280
        sio = self.make_utf8_encoded_stringio()
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
281
        lf = ShortLogFormatter(to_file=sio)
282
        show_log(b, lf)
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
283
        self.assertEqualDiff(sio.getvalue(), """\
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
284
    3 Joe Foo\t2005-11-21
285
      single line with trailing newline
286
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
287
    2 Joe Bar\t2005-11-21
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
288
      multiline
289
      log
290
      message
291
292
    1 Joe Foo\t2005-11-21
293
      simple log message
294
295
""")
296
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
297
    def test_short_log_with_merges(self):
298
        wt = self.make_branch_and_memory_tree('.')
299
        wt.lock_write()
300
        try:
301
            wt.add('')
302
            wt.commit('rev-1', rev_id='rev-1',
303
                      timestamp=1132586655, timezone=36000,
304
                      committer='Joe Foo <joe@foo.com>')
305
            wt.commit('rev-merged', rev_id='rev-2a',
306
                      timestamp=1132586700, timezone=36000,
307
                      committer='Joe Foo <joe@foo.com>')
308
            wt.set_parent_ids(['rev-1', 'rev-2a'])
309
            wt.branch.set_last_revision_info(1, 'rev-1')
310
            wt.commit('rev-2', rev_id='rev-2b',
311
                      timestamp=1132586800, timezone=36000,
312
                      committer='Joe Foo <joe@foo.com>')
313
            logfile = self.make_utf8_encoded_stringio()
314
            formatter = ShortLogFormatter(to_file=logfile)
315
            show_log(wt.branch, formatter)
316
            self.assertEqualDiff(logfile.getvalue(), """\
317
    2 Joe Foo\t2005-11-22 [merge]
318
      rev-2
319
320
    1 Joe Foo\t2005-11-22
321
      rev-1
322
323
""")
324
        finally:
325
            wt.unlock()
326
327
    def test_short_log_single_merge_revision(self):
328
        wt = self.make_branch_and_memory_tree('.')
329
        wt.lock_write()
330
        try:
331
            wt.add('')
332
            wt.commit('rev-1', rev_id='rev-1',
333
                      timestamp=1132586655, timezone=36000,
334
                      committer='Joe Foo <joe@foo.com>')
335
            wt.commit('rev-merged', rev_id='rev-2a',
336
                      timestamp=1132586700, timezone=36000,
337
                      committer='Joe Foo <joe@foo.com>')
338
            wt.set_parent_ids(['rev-1', 'rev-2a'])
339
            wt.branch.set_last_revision_info(1, 'rev-1')
340
            wt.commit('rev-2', rev_id='rev-2b',
341
                      timestamp=1132586800, timezone=36000,
342
                      committer='Joe Foo <joe@foo.com>')
343
            logfile = self.make_utf8_encoded_stringio()
344
            formatter = ShortLogFormatter(to_file=logfile)
345
            revspec = RevisionSpec.from_string('1.1.1')
346
            wtb = wt.branch
347
            rev = revspec.in_history(wtb)
348
            show_log(wtb, formatter, start_revision=rev, end_revision=rev)
349
            self.assertEqualDiff(logfile.getvalue(), """\
350
1.1.1 Joe Foo\t2005-11-22
351
      rev-merged
352
353
""")
354
        finally:
355
            wt.unlock()
356
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
357
358
class TestLongLogFormatter(TestCaseWithTransport):
359
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
360
    def test_verbose_log(self):
361
        """Verbose log includes changed files
362
        
363
        bug #4676
364
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
365
        wt = self.make_branch_and_tree('.')
366
        b = wt.branch
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
367
        self.build_tree(['a'])
1185.33.45 by Martin Pool
[merge] refactoring of branch vs working tree, etc (robertc)
368
        wt.add('a')
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
369
        # XXX: why does a longer nick show up?
370
        b.nick = 'test_verbose_log'
371
        wt.commit(message='add a', 
372
                  timestamp=1132711707, 
373
                  timezone=36000,
374
                  committer='Lorem Ipsum <test@example.com>')
375
        logfile = file('out.tmp', 'w+')
376
        formatter = LongLogFormatter(to_file=logfile)
377
        show_log(b, formatter, verbose=True)
378
        logfile.flush()
379
        logfile.seek(0)
380
        log_contents = logfile.read()
381
        self.assertEqualDiff(log_contents, '''\
382
------------------------------------------------------------
383
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
384
committer: Lorem Ipsum <test@example.com>
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
385
branch nick: test_verbose_log
386
timestamp: Wed 2005-11-23 12:08:27 +1000
387
message:
388
  add a
389
added:
390
  a
391
''')
1185.85.4 by John Arbash Meinel
currently broken, trying to fix things up.
392
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
393
    def test_merges_are_indented_by_level(self):
394
        wt = self.make_branch_and_tree('parent')
395
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
396
        self.run_bzr('branch parent child')
397
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
398
        self.run_bzr('branch child smallerchild')
399
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
400
            'smallerchild'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
401
        os.chdir('child')
2581.1.6 by Martin Pool
fix up more run_bzr callers
402
        self.run_bzr('merge ../smallerchild')
403
        self.run_bzr(['commit', '-m', 'merge branch 2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
404
        os.chdir('../parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
405
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
406
        wt.commit('merge branch 1')
407
        b = wt.branch
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
408
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
409
        lf = LongLogFormatter(to_file=sio)
410
        show_log(b, lf, verbose=True)
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
411
        log = normalize_log(sio.getvalue())
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
412
        self.assertEqualDiff(log, """\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
413
------------------------------------------------------------
414
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
415
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
416
branch nick: parent
417
timestamp: Just now
418
message:
419
  merge branch 1
420
    ------------------------------------------------------------
421
    revno: 1.1.2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
422
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
423
    branch nick: child
424
    timestamp: Just now
425
    message:
426
      merge branch 2
427
        ------------------------------------------------------------
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
428
        revno: 1.2.1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
429
        committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
430
        branch nick: smallerchild
431
        timestamp: Just now
432
        message:
433
          branch 2
434
    ------------------------------------------------------------
435
    revno: 1.1.1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
436
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
437
    branch nick: child
438
    timestamp: Just now
439
    message:
440
      branch 1
441
------------------------------------------------------------
442
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
443
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
444
branch nick: parent
445
timestamp: Just now
446
message:
447
  first post
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
448
""")
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
449
450
    def test_verbose_merge_revisions_contain_deltas(self):
451
        wt = self.make_branch_and_tree('parent')
452
        self.build_tree(['parent/f1', 'parent/f2'])
453
        wt.add(['f1','f2'])
454
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
455
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
456
        os.unlink('child/f1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
457
        file('child/f2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
458
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
459
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
460
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
461
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
462
        wt.commit('merge branch 1')
463
        b = wt.branch
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
464
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
465
        lf = LongLogFormatter(to_file=sio)
466
        show_log(b, lf, verbose=True)
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
467
        log = normalize_log(sio.getvalue())
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
468
        self.assertEqualDiff(log, """\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
469
------------------------------------------------------------
470
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
471
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
472
branch nick: parent
473
timestamp: Just now
474
message:
475
  merge branch 1
476
removed:
477
  f1
478
modified:
479
  f2
480
    ------------------------------------------------------------
481
    revno: 1.1.1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
482
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
483
    branch nick: child
484
    timestamp: Just now
485
    message:
486
      removed f1 and modified f2
487
    removed:
488
      f1
489
    modified:
490
      f2
491
------------------------------------------------------------
492
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
493
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
494
branch nick: parent
495
timestamp: Just now
496
message:
497
  first post
498
added:
499
  f1
500
  f2
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
501
""")
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
502
503
    def test_trailing_newlines(self):
504
        wt = self.make_branch_and_tree('.')
505
        b = make_commits_with_trailing_newlines(wt)
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
506
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
507
        lf = LongLogFormatter(to_file=sio)
508
        show_log(b, lf)
509
        self.assertEqualDiff(sio.getvalue(), """\
510
------------------------------------------------------------
511
revno: 3
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
512
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
513
branch nick: test
514
timestamp: Mon 2005-11-21 09:32:56 -0600
515
message:
516
  single line with trailing newline
517
------------------------------------------------------------
518
revno: 2
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
519
author: Joe Bar <joe@bar.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
520
committer: Joe Foo <joe@foo.com>
521
branch nick: test
522
timestamp: Mon 2005-11-21 09:27:22 -0600
523
message:
524
  multiline
525
  log
526
  message
527
------------------------------------------------------------
528
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
529
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
530
branch nick: test
531
timestamp: Mon 2005-11-21 09:24:15 -0600
532
message:
533
  simple log message
534
""")
535
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
536
    def test_author_in_log(self):
537
        """Log includes the author name if it's set in
538
        the revision properties
2671.2.1 by Lukáš Lalinský
Add --author option to 'bzr commit' to record the author's name, if it's different from the committer.
539
        """
540
        wt = self.make_branch_and_tree('.')
541
        b = wt.branch
542
        self.build_tree(['a'])
543
        wt.add('a')
544
        b.nick = 'test_author_log'
545
        wt.commit(message='add a',
546
                  timestamp=1132711707,
547
                  timezone=36000,
548
                  committer='Lorem Ipsum <test@example.com>',
2671.2.5 by Lukáš Lalinský
Fixes for comments from the mailing list.
549
                  author='John Doe <jdoe@example.com>')
2671.2.1 by Lukáš Lalinský
Add --author option to 'bzr commit' to record the author's name, if it's different from the committer.
550
        sio = StringIO()
551
        formatter = LongLogFormatter(to_file=sio)
552
        show_log(b, formatter)
553
        self.assertEqualDiff(sio.getvalue(), '''\
554
------------------------------------------------------------
555
revno: 1
556
author: John Doe <jdoe@example.com>
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
557
committer: Lorem Ipsum <test@example.com>
2671.2.1 by Lukáš Lalinský
Add --author option to 'bzr commit' to record the author's name, if it's different from the committer.
558
branch nick: test_author_log
559
timestamp: Wed 2005-11-23 12:08:27 +1000
560
message:
561
  add a
562
''')
563
564
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
565
566
class TestLineLogFormatter(TestCaseWithTransport):
567
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
568
    def test_line_log(self):
569
        """Line log should show revno
570
        
571
        bug #5162
572
        """
573
        wt = self.make_branch_and_tree('.')
574
        b = wt.branch
575
        self.build_tree(['a'])
576
        wt.add('a')
577
        b.nick = 'test-line-log'
578
        wt.commit(message='add a', 
579
                  timestamp=1132711707, 
580
                  timezone=36000,
581
                  committer='Line-Log-Formatter Tester <test@line.log>')
582
        logfile = file('out.tmp', 'w+')
583
        formatter = LineLogFormatter(to_file=logfile)
584
        show_log(b, formatter)
585
        logfile.flush()
586
        logfile.seek(0)
587
        log_contents = logfile.read()
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
588
        self.assertEqualDiff(log_contents,
589
            '1: Line-Log-Formatte... 2005-11-23 add a\n')
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
590
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
591
    def test_trailing_newlines(self):
592
        wt = self.make_branch_and_tree('.')
593
        b = make_commits_with_trailing_newlines(wt)
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
594
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
595
        lf = LineLogFormatter(to_file=sio)
596
        show_log(b, lf)
597
        self.assertEqualDiff(sio.getvalue(), """\
598
3: Joe Foo 2005-11-21 single line with trailing newline
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
599
2: Joe Bar 2005-11-21 multiline
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
600
1: Joe Foo 2005-11-21 simple log message
601
""")
602
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
603
    def test_line_log_single_merge_revision(self):
604
        wt = self.make_branch_and_memory_tree('.')
605
        wt.lock_write()
606
        try:
607
            wt.add('')
608
            wt.commit('rev-1', rev_id='rev-1',
609
                      timestamp=1132586655, timezone=36000,
610
                      committer='Joe Foo <joe@foo.com>')
611
            wt.commit('rev-merged', rev_id='rev-2a',
612
                      timestamp=1132586700, timezone=36000,
613
                      committer='Joe Foo <joe@foo.com>')
614
            wt.set_parent_ids(['rev-1', 'rev-2a'])
615
            wt.branch.set_last_revision_info(1, 'rev-1')
616
            wt.commit('rev-2', rev_id='rev-2b',
617
                      timestamp=1132586800, timezone=36000,
618
                      committer='Joe Foo <joe@foo.com>')
619
            logfile = self.make_utf8_encoded_stringio()
620
            formatter = LineLogFormatter(to_file=logfile)
621
            revspec = RevisionSpec.from_string('1.1.1')
622
            wtb = wt.branch
623
            rev = revspec.in_history(wtb)
624
            show_log(wtb, formatter, start_revision=rev, end_revision=rev)
625
            self.assertEqualDiff(logfile.getvalue(), """\
626
1.1.1: Joe Foo 2005-11-22 rev-merged
627
""")
628
        finally:
629
            wt.unlock()
630
631
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
632
633
class TestGetViewRevisions(TestCaseWithTransport):
634
1756.2.22 by Aaron Bentley
Apply review comments
635
    def make_tree_with_commits(self):
636
        """Create a tree with well-known revision ids"""
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
637
        wt = self.make_branch_and_tree('tree1')
638
        wt.commit('commit one', rev_id='1')
639
        wt.commit('commit two', rev_id='2')
640
        wt.commit('commit three', rev_id='3')
641
        mainline_revs = [None, '1', '2', '3']
1756.2.22 by Aaron Bentley
Apply review comments
642
        rev_nos = {'1': 1, '2': 2, '3': 3}
643
        return mainline_revs, rev_nos, wt
644
645
    def make_tree_with_merges(self):
646
        """Create a tree with well-known revision ids and a merge"""
647
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
648
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
649
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
650
        wt.merge_from_branch(tree2.branch)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
651
        wt.commit('four-b', rev_id='4b')
652
        mainline_revs.append('4b')
1756.2.22 by Aaron Bentley
Apply review comments
653
        rev_nos['4b'] = 4
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
654
        # 4a: 3.1.1
1756.2.22 by Aaron Bentley
Apply review comments
655
        return mainline_revs, rev_nos, wt
656
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
657
    def make_tree_with_many_merges(self):
658
        """Create a tree with well-known revision ids"""
659
        wt = self.make_branch_and_tree('tree1')
660
        wt.commit('commit one', rev_id='1')
661
        wt.commit('commit two', rev_id='2')
662
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
663
        tree3.commit('commit three a', rev_id='3a')
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
664
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
665
        tree2.merge_from_branch(tree3.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
666
        tree2.commit('commit three b', rev_id='3b')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
667
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
668
        wt.commit('commit three c', rev_id='3c')
669
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
670
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
671
        wt.commit('four-b', rev_id='4b')
672
        mainline_revs = [None, '1', '2', '3c', '4b']
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
673
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
674
        full_rev_nos_for_reference = {
675
            '1': '1',
676
            '2': '2',
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
677
            '3a': '2.1.1', #first commit tree 3
678
            '3b': '2.2.1', # first commit tree 2
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
679
            '3c': '3', #merges 3b to main
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
680
            '4a': '2.2.2', # second commit tree 2
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
681
            '4b': '4', # merges 4a to main
682
            }
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
683
        return mainline_revs, rev_nos, wt
684
1756.2.22 by Aaron Bentley
Apply review comments
685
    def test_get_view_revisions_forward(self):
686
        """Test the get_view_revisions method"""
687
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
688
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
689
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
690
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
691
            revisions)
1756.2.22 by Aaron Bentley
Apply review comments
692
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
693
                                             'forward', include_merges=False))
694
        self.assertEqual(revisions, revisions2)
695
696
    def test_get_view_revisions_reverse(self):
697
        """Test the get_view_revisions with reverse"""
698
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
699
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
700
                                            'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
701
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
702
            revisions)
1756.2.22 by Aaron Bentley
Apply review comments
703
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
704
                                             'reverse', include_merges=False))
705
        self.assertEqual(revisions, revisions2)
706
707
    def test_get_view_revisions_merge(self):
708
        """Test get_view_revisions when there are merges"""
709
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
710
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
711
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
712
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
713
            ('4b', '4', 0), ('4a', '3.1.1', 1)],
714
            revisions)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
715
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
1756.2.22 by Aaron Bentley
Apply review comments
716
                                             'forward', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
717
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
718
            ('4b', '4', 0)],
719
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
720
721
    def test_get_view_revisions_merge_reverse(self):
722
        """Test get_view_revisions in reverse when there are merges"""
723
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
724
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
725
                                            'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
726
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
727
            ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
728
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
729
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
730
                                             'reverse', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
731
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
732
            ('1', '1', 0)],
733
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
734
735
    def test_get_view_revisions_merge2(self):
736
        """Test get_view_revisions when there are merges"""
737
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
738
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
739
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
740
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
741
            ('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
742
            ('4a', '2.2.2', 1)]
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
743
        self.assertEqual(expected, revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
744
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
745
                                             'forward', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
746
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
747
            ('4b', '4', 0)],
748
            revisions)
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
749
750
751
class TestGetRevisionsTouchingFileID(TestCaseWithTransport):
752
753
    def create_tree_with_single_merge(self):
754
        """Create a branch with a moderate layout.
755
756
        The revision graph looks like:
757
758
           A
759
           |\
760
           B C
761
           |/
762
           D
763
764
        In this graph, A introduced files f1 and f2 and f3.
765
        B modifies f1 and f3, and C modifies f2 and f3.
766
        D merges the changes from B and C and resolves the conflict for f3.
767
        """
768
        # TODO: jam 20070218 This seems like it could really be done
769
        #       with make_branch_and_memory_tree() if we could just
770
        #       create the content of those files.
771
        # TODO: jam 20070218 Another alternative is that we would really
772
        #       like to only create this tree 1 time for all tests that
773
        #       use it. Since 'log' only uses the tree in a readonly
774
        #       fashion, it seems a shame to regenerate an identical
775
        #       tree for each test.
776
        tree = self.make_branch_and_tree('tree')
777
        tree.lock_write()
778
        self.addCleanup(tree.unlock)
779
780
        self.build_tree_contents([('tree/f1', 'A\n'),
781
                                  ('tree/f2', 'A\n'),
782
                                  ('tree/f3', 'A\n'),
783
                                 ])
784
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
785
        tree.commit('A', rev_id='A')
786
787
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
788
                                  ('tree/f3', 'A\nC\n'),
789
                                 ])
790
        tree.commit('C', rev_id='C')
791
        # Revert back to A to build the other history.
792
        tree.set_last_revision('A')
793
        tree.branch.set_last_revision_info(1, 'A')
794
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
795
                                  ('tree/f2', 'A\n'),
796
                                  ('tree/f3', 'A\nB\n'),
797
                                 ])
798
        tree.commit('B', rev_id='B')
799
        tree.set_parent_ids(['B', 'C'])
800
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
801
                                  ('tree/f2', 'A\nC\n'),
802
                                  ('tree/f3', 'A\nB\nC\n'),
803
                                 ])
804
        tree.commit('D', rev_id='D')
805
806
        # Switch to a read lock for this tree.
807
        # We still have addCleanup(unlock)
808
        tree.unlock()
809
        tree.lock_read()
810
        return tree
811
812
    def test_tree_with_single_merge(self):
813
        """Make sure the tree layout is correct."""
814
        tree = self.create_tree_with_single_merge()
815
        rev_A_tree = tree.branch.repository.revision_tree('A')
816
        rev_B_tree = tree.branch.repository.revision_tree('B')
817
818
        f1_changed = (u'f1', 'f1-id', 'file', True, False)
819
        f2_changed = (u'f2', 'f2-id', 'file', True, False)
820
        f3_changed = (u'f3', 'f3-id', 'file', True, False)
821
822
        delta = rev_B_tree.changes_from(rev_A_tree)
823
        self.assertEqual([f1_changed, f3_changed], delta.modified)
824
        self.assertEqual([], delta.renamed)
825
        self.assertEqual([], delta.added)
826
        self.assertEqual([], delta.removed)
827
828
        rev_C_tree = tree.branch.repository.revision_tree('C')
829
        delta = rev_C_tree.changes_from(rev_A_tree)
830
        self.assertEqual([f2_changed, f3_changed], delta.modified)
831
        self.assertEqual([], delta.renamed)
832
        self.assertEqual([], delta.added)
833
        self.assertEqual([], delta.removed)
834
835
        rev_D_tree = tree.branch.repository.revision_tree('D')
836
        delta = rev_D_tree.changes_from(rev_B_tree)
837
        self.assertEqual([f2_changed, f3_changed], delta.modified)
838
        self.assertEqual([], delta.renamed)
839
        self.assertEqual([], delta.added)
840
        self.assertEqual([], delta.removed)
841
842
        delta = rev_D_tree.changes_from(rev_C_tree)
843
        self.assertEqual([f1_changed, f3_changed], delta.modified)
844
        self.assertEqual([], delta.renamed)
845
        self.assertEqual([], delta.added)
846
        self.assertEqual([], delta.removed)
847
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
848
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
849
        """Make sure _filter_revisions_touching_file_id returns the right values.
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
850
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
851
        Get the return value from _filter_revisions_touching_file_id and make
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
852
        sure they are correct.
853
        """
854
        # The api for _get_revisions_touching_file_id is a little crazy,
855
        # So we do the setup here.
856
        mainline = tree.branch.revision_history()
857
        mainline.insert(0, None)
858
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
859
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
860
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
861
        actual_revs = log._filter_revisions_touching_file_id(
862
                            tree.branch, 
863
                            file_id,
864
                            mainline,
865
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
866
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
867
868
    def test_file_id_f1(self):
869
        tree = self.create_tree_with_single_merge()
870
        # f1 should be marked as modified by revisions A and B
871
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
872
873
    def test_file_id_f2(self):
874
        tree = self.create_tree_with_single_merge()
875
        # f2 should be marked as modified by revisions A, C, and D
876
        # because D merged the changes from C.
877
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
878
879
    def test_file_id_f3(self):
880
        tree = self.create_tree_with_single_merge()
881
        # f3 should be marked as modified by revisions A, B, C, and D
882
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
883
884
885
class TestShowChangedRevisions(TestCaseWithTransport):
886
887
    def test_show_changed_revisions_verbose(self):
888
        tree = self.make_branch_and_tree('tree_a')
889
        self.build_tree(['tree_a/foo'])
890
        tree.add('foo')
891
        tree.commit('bar', rev_id='bar-id')
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
892
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
893
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
894
        self.assertContainsRe(s.getvalue(), 'bar')
895
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
896
897
898
class TestLogFormatter(TestCase):
899
900
    def test_short_committer(self):
901
        rev = Revision('a-id')
902
        rev.committer = 'John Doe <jdoe@example.com>'
903
        lf = LogFormatter(None)
904
        self.assertEqual('John Doe', lf.short_committer(rev))
3063.3.1 by Lukáš Lalinský
Fall back to showing e-mail in ``log --short/--line`` if the committer/author has only e-mail.
905
        rev.committer = 'John Smith <jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
906
        self.assertEqual('John Smith', lf.short_committer(rev))
3063.3.1 by Lukáš Lalinský
Fall back to showing e-mail in ``log --short/--line`` if the committer/author has only e-mail.
907
        rev.committer = 'John Smith'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
908
        self.assertEqual('John Smith', lf.short_committer(rev))
3063.3.1 by Lukáš Lalinský
Fall back to showing e-mail in ``log --short/--line`` if the committer/author has only e-mail.
909
        rev.committer = 'jsmith@example.com'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
910
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
3063.3.1 by Lukáš Lalinský
Fall back to showing e-mail in ``log --short/--line`` if the committer/author has only e-mail.
911
        rev.committer = '<jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
912
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
913
        rev.committer = 'John Smith jsmith@example.com'
914
        self.assertEqual('John Smith', lf.short_committer(rev))
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
915
916
    def test_short_author(self):
917
        rev = Revision('a-id')
918
        rev.committer = 'John Doe <jdoe@example.com>'
919
        lf = LogFormatter(None)
920
        self.assertEqual('John Doe', lf.short_author(rev))
921
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
922
        self.assertEqual('John Smith', lf.short_author(rev))
3063.3.1 by Lukáš Lalinský
Fall back to showing e-mail in ``log --short/--line`` if the committer/author has only e-mail.
923
        rev.properties['author'] = 'John Smith'
924
        self.assertEqual('John Smith', lf.short_author(rev))
925
        rev.properties['author'] = 'jsmith@example.com'
926
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
927
        rev.properties['author'] = '<jsmith@example.com>'
928
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
929
        rev.properties['author'] = 'John Smith jsmith@example.com'
930
        self.assertEqual('John Smith', lf.short_author(rev))