/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
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
20
from bzrlib import (
21
    errors,
22
    log,
23
    registry,
24
    revision,
25
    revisionspec,
26
    tests,
27
    )
28
29
30
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
31
32
    def setUp(self):
33
        super(TestCaseWithoutPropsHandler, self).setUp()
34
        # keep a reference to the "current" custom prop. handler registry
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
35
        self.properties_handler_registry = log.properties_handler_registry
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
36
        # clean up the registry in log
37
        log.properties_handler_registry = registry.Registry()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
38
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
39
    def _cleanup(self):
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
40
        super(TestCaseWithoutPropsHandler, self)._cleanup()
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
41
        # restore the custom properties handler registry
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
42
        log.properties_handler_registry = self.properties_handler_registry
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
43
44
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
45
class LogCatcher(log.LogFormatter):
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
46
    """Pull log messages into list rather than displaying them.
47
48
    For ease of testing we save log messages here rather than actually
49
    formatting them, so that we can precisely check the result without
50
    being too dependent on the exact formatting.
51
52
    We should also test the LogFormatter.
53
    """
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.
54
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
55
    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.
56
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
57
    def __init__(self):
58
        super(LogCatcher, self).__init__(to_file=None)
59
        self.logs = []
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
60
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.
61
    def log_revision(self, revision):
62
        self.logs.append(revision)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
63
64
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
65
class TestShowLog(tests.TestCaseWithTransport):
1102 by Martin Pool
- merge test refactoring from robertc
66
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
67
    def checkDelta(self, delta, **kw):
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
68
        """Check the filenames touched by a delta are as expected.
69
70
        Caller only have to pass in the list of files for each part, all
71
        unspecified parts are considered empty (and checked as such).
72
        """
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
73
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
74
            # By default we expect an empty list
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
75
            expected = kw.get(n, [])
76
            # strip out only the path components
77
            got = [x[0] for x in getattr(delta, n)]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
78
            self.assertEqual(expected, got)
79
80
    def assertInvalidRevisonNumber(self, br, start, end):
81
        lf = LogCatcher()
82
        self.assertRaises(errors.InvalidRevisionNumber,
83
                          log.show_log, br, lf,
84
                          start_revision=start, end_revision=end)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
85
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
86
    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.
87
        wt = self.make_branch_and_tree('.')
88
        b = wt.branch
1092.3.4 by Robert Collins
update symlink branch to integration
89
90
        lf = LogCatcher()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
91
        wt.commit('empty commit')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
92
        log.show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
93
94
        # Since there is a single revision in the branch all the combinations
95
        # below should fail.
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
96
        self.assertInvalidRevisonNumber(b, 2, 1)
97
        self.assertInvalidRevisonNumber(b, 1, 2)
98
        self.assertInvalidRevisonNumber(b, 0, 2)
99
        self.assertInvalidRevisonNumber(b, 1, 0)
100
        self.assertInvalidRevisonNumber(b, -1, 1)
101
        self.assertInvalidRevisonNumber(b, 1, -1)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
102
103
    def test_empty_branch(self):
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
104
        wt = self.make_branch_and_tree('.')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
105
106
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
107
        log.show_log(wt.branch, lf)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
108
        # no entries yet
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
109
        self.assertEqual([], lf.logs)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
110
111
    def test_empty_commit(self):
112
        wt = self.make_branch_and_tree('.')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
113
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
114
        wt.commit('empty commit')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
115
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
116
        log.show_log(wt.branch, lf, verbose=True)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
117
        self.assertEqual(1, len(lf.logs))
118
        self.assertEqual('1', lf.logs[0].revno)
119
        self.assertEqual('empty commit', lf.logs[0].rev.message)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
120
        self.checkDelta(lf.logs[0].delta)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
121
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
122
    def test_simple_commit(self):
123
        wt = self.make_branch_and_tree('.')
124
        wt.commit('empty commit')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
125
        self.build_tree(['hello'])
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
126
        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.
127
        wt.commit('add one file',
128
                  committer=u'\u013d\xf3r\xe9m \xcdp\u0161\xfam '
129
                            u'<test@example.com>')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
130
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
131
        log.show_log(wt.branch, lf, verbose=True)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
132
        self.assertEqual(2, len(lf.logs))
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
133
        # first one is most recent
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
134
        log_entry = lf.logs[0]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
135
        self.assertEqual('2', log_entry.revno)
136
        self.assertEqual('add one file', log_entry.rev.message)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
137
        self.checkDelta(log_entry.delta, added=['hello'])
3831.1.6 by John Arbash Meinel
For the simple-log tests, avoid using '\r' in the test.
138
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
139
    def test_commit_message_with_control_chars(self):
140
        wt = self.make_branch_and_tree('.')
3831.1.6 by John Arbash Meinel
For the simple-log tests, avoid using '\r' in the test.
141
        msg = u"All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
142
        msg = msg.replace(u'\r', u'\n')
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
143
        wt.commit(msg)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
144
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
145
        log.show_log(wt.branch, lf, verbose=True)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
146
        committed_msg = lf.logs[0].rev.message
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
147
        self.assertNotEqual(msg, committed_msg)
148
        self.assertTrue(len(committed_msg) > len(msg))
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
149
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
150
    def test_commit_message_without_control_chars(self):
151
        wt = self.make_branch_and_tree('.')
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
152
        # escaped.  As ElementTree apparently does some kind of
153
        # newline conversion, neither LF (\x0A) nor CR (\x0D) are
154
        # included in the test commit message, even though they are
155
        # valid XML 1.0 characters.
156
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
157
        wt.commit(msg)
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
158
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
159
        log.show_log(wt.branch, lf, verbose=True)
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
160
        committed_msg = lf.logs[0].rev.message
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
161
        self.assertEqual(msg, committed_msg)
1185.31.22 by John Arbash Meinel
[merge] bzr.dev
162
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
163
    def test_deltas_in_merge_revisions(self):
164
        """Check deltas created for both mainline and merge revisions"""
165
        wt = self.make_branch_and_tree('parent')
166
        self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
167
        wt.add('file1')
168
        wt.add('file2')
169
        wt.commit(message='add file1 and file2')
2581.1.6 by Martin Pool
fix up more run_bzr callers
170
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
171
        os.unlink('child/file1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
172
        file('child/file2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
173
        self.run_bzr(['commit', '-m', 'remove file1 and modify file2',
174
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
175
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
176
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
177
        wt.commit('merge child branch')
178
        os.chdir('..')
179
        b = wt.branch
180
        lf = LogCatcher()
181
        lf.supports_merge_revisions = True
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
182
        log.show_log(b, lf, verbose=True)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
183
184
        self.assertEqual(3, len(lf.logs))
185
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
186
        logentry = lf.logs[0]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
187
        self.assertEqual('2', logentry.revno)
188
        self.assertEqual('merge child branch', logentry.rev.message)
189
        self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
190
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
191
        logentry = lf.logs[1]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
192
        self.assertEqual('1.1.1', logentry.revno)
193
        self.assertEqual('remove file1 and modify file2', logentry.rev.message)
194
        self.checkDelta(logentry.delta, removed=['file1'], modified=['file2'])
195
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
196
        logentry = lf.logs[2]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
197
        self.assertEqual('1', logentry.revno)
198
        self.assertEqual('add file1 and file2', logentry.rev.message)
199
        self.checkDelta(logentry.delta, added=['file1', 'file2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
200
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
201
    def test_merges_nonsupporting_formatter(self):
202
        """Tests that show_log will raise if the formatter doesn't
203
        support merge revisions."""
204
        wt = self.make_branch_and_memory_tree('.')
205
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
206
        self.addCleanup(wt.unlock)
207
        wt.add('')
208
        wt.commit('rev-1', rev_id='rev-1',
209
                  timestamp=1132586655, timezone=36000,
210
                  committer='Joe Foo <joe@foo.com>')
211
        wt.commit('rev-merged', rev_id='rev-2a',
212
                  timestamp=1132586700, timezone=36000,
213
                  committer='Joe Foo <joe@foo.com>')
214
        wt.set_parent_ids(['rev-1', 'rev-2a'])
215
        wt.branch.set_last_revision_info(1, 'rev-1')
216
        wt.commit('rev-2', rev_id='rev-2b',
217
                  timestamp=1132586800, timezone=36000,
218
                  committer='Joe Foo <joe@foo.com>')
219
        logfile = self.make_utf8_encoded_stringio()
220
        formatter = log.ShortLogFormatter(to_file=logfile)
221
        wtb = wt.branch
222
        lf = LogCatcher()
223
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
224
        rev = revspec.in_history(wtb)
225
        self.assertRaises(errors.BzrCommandError, log.show_log, wtb, lf,
3936.3.8 by Ian Clatworthy
back-out --strict
226
                          start_revision=rev, end_revision=rev)
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
227
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
228
229
def make_commits_with_trailing_newlines(wt):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
230
    """Helper method for LogFormatter tests"""
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
231
    b = wt.branch
232
    b.nick='test'
233
    open('a', 'wb').write('hello moto\n')
234
    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.
235
    wt.commit('simple log message', rev_id='a1',
236
              timestamp=1132586655.459960938, timezone=-6*3600,
237
              committer='Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
238
    open('b', 'wb').write('goodbye\n')
239
    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.
240
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
241
              timestamp=1132586842.411175966, timezone=-6*3600,
242
              committer='Joe Foo <joe@foo.com>',
243
              author='Joe Bar <joe@bar.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
244
245
    open('c', 'wb').write('just another manic monday\n')
246
    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.
247
    wt.commit('single line with trailing newline\n', rev_id='a3',
248
              timestamp=1132587176.835228920, timezone=-6*3600,
249
              committer = 'Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
250
    return b
251
252
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
253
def normalize_log(log):
254
    """Replaces the variable lines of logs with fixed lines"""
255
    author = 'author: Dolor Sit <test@example.com>'
256
    committer = 'committer: Lorem Ipsum <test@example.com>'
257
    lines = log.splitlines(True)
258
    for idx,line in enumerate(lines):
259
        stripped_line = line.lstrip()
260
        indent = ' ' * (len(line) - len(stripped_line))
261
        if stripped_line.startswith('author:'):
262
            lines[idx] = indent + author + '\n'
263
        elif stripped_line.startswith('committer:'):
264
            lines[idx] = indent + committer + '\n'
265
        elif stripped_line.startswith('timestamp:'):
266
            lines[idx] = indent + 'timestamp: Just now\n'
267
    return ''.join(lines)
268
269
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
270
class TestShortLogFormatter(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
271
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
272
    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.
273
        wt = self.make_branch_and_tree('.')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
274
        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.
275
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
276
        lf = log.ShortLogFormatter(to_file=sio)
277
        log.show_log(b, lf)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
278
        self.assertEqualDiff("""\
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
279
    3 Joe Foo\t2005-11-21
280
      single line with trailing newline
281
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.
282
    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.
283
      multiline
284
      log
285
      message
286
287
    1 Joe Foo\t2005-11-21
288
      simple log message
289
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
290
""",
291
                             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.
292
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
293
    def test_short_log_with_merges(self):
294
        wt = self.make_branch_and_memory_tree('.')
295
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
296
        self.addCleanup(wt.unlock)
297
        wt.add('')
298
        wt.commit('rev-1', rev_id='rev-1',
299
                  timestamp=1132586655, timezone=36000,
300
                  committer='Joe Foo <joe@foo.com>')
301
        wt.commit('rev-merged', rev_id='rev-2a',
302
                  timestamp=1132586700, timezone=36000,
303
                  committer='Joe Foo <joe@foo.com>')
3943.4.3 by John Arbash Meinel
Revert one test change, and the special case of logging all-of-mainline.
304
        wt.set_parent_ids(['rev-1', 'rev-2a'])
3943.4.2 by John Arbash Meinel
Add a test case which exercises this code path.
305
        wt.branch.set_last_revision_info(1, 'rev-1')
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
306
        wt.commit('rev-2', rev_id='rev-2b',
307
                  timestamp=1132586800, timezone=36000,
308
                  committer='Joe Foo <joe@foo.com>')
309
        logfile = self.make_utf8_encoded_stringio()
310
        formatter = log.ShortLogFormatter(to_file=logfile)
311
        log.show_log(wt.branch, formatter)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
312
        self.assertEqualDiff("""\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
313
    2 Joe Foo\t2005-11-22 [merge]
314
      rev-2
315
316
    1 Joe Foo\t2005-11-22
317
      rev-1
318
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
319
""",
320
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
321
3943.4.2 by John Arbash Meinel
Add a test case which exercises this code path.
322
    def test_short_log_with_merges_and_range(self):
323
        wt = self.make_branch_and_memory_tree('.')
324
        wt.lock_write()
325
        self.addCleanup(wt.unlock)
326
        wt.add('')
327
        wt.commit('rev-1', rev_id='rev-1',
328
                  timestamp=1132586655, timezone=36000,
329
                  committer='Joe Foo <joe@foo.com>')
330
        wt.commit('rev-merged', rev_id='rev-2a',
331
                  timestamp=1132586700, timezone=36000,
332
                  committer='Joe Foo <joe@foo.com>')
333
        wt.branch.set_last_revision_info(1, 'rev-1')
334
        wt.set_parent_ids(['rev-1', 'rev-2a'])
335
        wt.commit('rev-2b', rev_id='rev-2b',
336
                  timestamp=1132586800, timezone=36000,
337
                  committer='Joe Foo <joe@foo.com>')
338
        wt.commit('rev-3a', rev_id='rev-3a',
339
                  timestamp=1132586800, timezone=36000,
340
                  committer='Joe Foo <joe@foo.com>')
341
        wt.branch.set_last_revision_info(2, 'rev-2b')
342
        wt.set_parent_ids(['rev-2b', 'rev-3a'])
343
        wt.commit('rev-3b', rev_id='rev-3b',
344
                  timestamp=1132586800, timezone=36000,
345
                  committer='Joe Foo <joe@foo.com>')
346
        logfile = self.make_utf8_encoded_stringio()
347
        formatter = log.ShortLogFormatter(to_file=logfile)
348
        log.show_log(wt.branch, formatter,
349
            start_revision=2, end_revision=3)
350
        self.assertEqualDiff("""\
351
    3 Joe Foo\t2005-11-22 [merge]
352
      rev-3b
353
354
    2 Joe Foo\t2005-11-22 [merge]
355
      rev-2b
356
357
""",
358
                             logfile.getvalue())
359
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
360
    def test_short_log_single_merge_revision(self):
361
        wt = self.make_branch_and_memory_tree('.')
362
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
363
        self.addCleanup(wt.unlock)
364
        wt.add('')
365
        wt.commit('rev-1', rev_id='rev-1',
366
                  timestamp=1132586655, timezone=36000,
367
                  committer='Joe Foo <joe@foo.com>')
368
        wt.commit('rev-merged', rev_id='rev-2a',
369
                  timestamp=1132586700, timezone=36000,
370
                  committer='Joe Foo <joe@foo.com>')
371
        wt.set_parent_ids(['rev-1', 'rev-2a'])
372
        wt.branch.set_last_revision_info(1, 'rev-1')
373
        wt.commit('rev-2', rev_id='rev-2b',
374
                  timestamp=1132586800, timezone=36000,
375
                  committer='Joe Foo <joe@foo.com>')
376
        logfile = self.make_utf8_encoded_stringio()
377
        formatter = log.ShortLogFormatter(to_file=logfile)
378
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
379
        wtb = wt.branch
380
        rev = revspec.in_history(wtb)
381
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
382
        self.assertEqualDiff("""\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
383
1.1.1 Joe Foo\t2005-11-22
384
      rev-merged
385
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
386
""",
387
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
388
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
389
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
390
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
391
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
392
    def test_verbose_log(self):
393
        """Verbose log includes changed files
394
        
395
        bug #4676
396
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
397
        wt = self.make_branch_and_tree('.')
398
        b = wt.branch
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
399
        self.build_tree(['a'])
1185.33.45 by Martin Pool
[merge] refactoring of branch vs working tree, etc (robertc)
400
        wt.add('a')
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
401
        # XXX: why does a longer nick show up?
402
        b.nick = 'test_verbose_log'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
403
        wt.commit(message='add a',
404
                  timestamp=1132711707,
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
405
                  timezone=36000,
406
                  committer='Lorem Ipsum <test@example.com>')
407
        logfile = file('out.tmp', 'w+')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
408
        formatter = log.LongLogFormatter(to_file=logfile)
409
        log.show_log(b, formatter, verbose=True)
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
410
        logfile.flush()
411
        logfile.seek(0)
412
        log_contents = logfile.read()
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
413
        self.assertEqualDiff('''\
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
414
------------------------------------------------------------
415
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
416
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)
417
branch nick: test_verbose_log
418
timestamp: Wed 2005-11-23 12:08:27 +1000
419
message:
420
  add a
421
added:
422
  a
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
423
''',
424
                             log_contents)
1185.85.4 by John Arbash Meinel
currently broken, trying to fix things up.
425
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
426
    def test_merges_are_indented_by_level(self):
427
        wt = self.make_branch_and_tree('parent')
428
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
429
        self.run_bzr('branch parent child')
430
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
431
        self.run_bzr('branch child smallerchild')
432
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
433
            'smallerchild'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
434
        os.chdir('child')
2581.1.6 by Martin Pool
fix up more run_bzr callers
435
        self.run_bzr('merge ../smallerchild')
436
        self.run_bzr(['commit', '-m', 'merge branch 2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
437
        os.chdir('../parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
438
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
439
        wt.commit('merge branch 1')
440
        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.
441
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
442
        lf = log.LongLogFormatter(to_file=sio)
443
        log.show_log(b, lf, verbose=True)
444
        the_log = normalize_log(sio.getvalue())
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
445
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
446
------------------------------------------------------------
447
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
448
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
449
branch nick: parent
450
timestamp: Just now
451
message:
452
  merge branch 1
453
    ------------------------------------------------------------
454
    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.
455
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
456
    branch nick: child
457
    timestamp: Just now
458
    message:
459
      merge branch 2
460
        ------------------------------------------------------------
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
461
        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.
462
        committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
463
        branch nick: smallerchild
464
        timestamp: Just now
465
        message:
466
          branch 2
467
    ------------------------------------------------------------
468
    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.
469
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
470
    branch nick: child
471
    timestamp: Just now
472
    message:
473
      branch 1
474
------------------------------------------------------------
475
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
476
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
477
branch nick: parent
478
timestamp: Just now
479
message:
480
  first post
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
481
""",
482
                             the_log)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
483
484
    def test_verbose_merge_revisions_contain_deltas(self):
485
        wt = self.make_branch_and_tree('parent')
486
        self.build_tree(['parent/f1', 'parent/f2'])
487
        wt.add(['f1','f2'])
488
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
489
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
490
        os.unlink('child/f1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
491
        file('child/f2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
492
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
493
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
494
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
495
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
496
        wt.commit('merge branch 1')
497
        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.
498
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
499
        lf = log.LongLogFormatter(to_file=sio)
500
        log.show_log(b, lf, verbose=True)
501
        the_log = normalize_log(sio.getvalue())
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
502
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
503
------------------------------------------------------------
504
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
505
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
506
branch nick: parent
507
timestamp: Just now
508
message:
509
  merge branch 1
510
removed:
511
  f1
512
modified:
513
  f2
514
    ------------------------------------------------------------
515
    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.
516
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
517
    branch nick: child
518
    timestamp: Just now
519
    message:
520
      removed f1 and modified f2
521
    removed:
522
      f1
523
    modified:
524
      f2
525
------------------------------------------------------------
526
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
527
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
528
branch nick: parent
529
timestamp: Just now
530
message:
531
  first post
532
added:
533
  f1
534
  f2
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
535
""",
536
                             the_log)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
537
538
    def test_trailing_newlines(self):
539
        wt = self.make_branch_and_tree('.')
540
        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.
541
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
542
        lf = log.LongLogFormatter(to_file=sio)
543
        log.show_log(b, lf)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
544
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
545
------------------------------------------------------------
546
revno: 3
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
547
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
548
branch nick: test
549
timestamp: Mon 2005-11-21 09:32:56 -0600
550
message:
551
  single line with trailing newline
552
------------------------------------------------------------
553
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.
554
author: Joe Bar <joe@bar.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
555
committer: Joe Foo <joe@foo.com>
556
branch nick: test
557
timestamp: Mon 2005-11-21 09:27:22 -0600
558
message:
559
  multiline
560
  log
561
  message
562
------------------------------------------------------------
563
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
564
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
565
branch nick: test
566
timestamp: Mon 2005-11-21 09:24:15 -0600
567
message:
568
  simple log message
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
569
""",
570
                             sio.getvalue())
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
571
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
572
    def test_author_in_log(self):
573
        """Log includes the author name if it's set in
574
        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.
575
        """
576
        wt = self.make_branch_and_tree('.')
577
        b = wt.branch
578
        self.build_tree(['a'])
579
        wt.add('a')
580
        b.nick = 'test_author_log'
581
        wt.commit(message='add a',
582
                  timestamp=1132711707,
583
                  timezone=36000,
584
                  committer='Lorem Ipsum <test@example.com>',
2671.2.5 by Lukáš Lalinský
Fixes for comments from the mailing list.
585
                  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.
586
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
587
        formatter = log.LongLogFormatter(to_file=sio)
588
        log.show_log(b, formatter)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
589
        self.assertEqualDiff('''\
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.
590
------------------------------------------------------------
591
revno: 1
592
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.
593
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.
594
branch nick: test_author_log
595
timestamp: Wed 2005-11-23 12:08:27 +1000
596
message:
597
  add a
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
598
''',
599
                             sio.getvalue())
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.
600
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
601
    def test_properties_in_log(self):
602
        """Log includes the custom properties returned by the registered 
603
        handlers.
604
        """
605
        wt = self.make_branch_and_tree('.')
606
        b = wt.branch
607
        self.build_tree(['a'])
608
        wt.add('a')
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
609
        b.nick = 'test_properties_in_log'
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
610
        wt.commit(message='add a',
611
                  timestamp=1132711707,
612
                  timezone=36000,
613
                  committer='Lorem Ipsum <test@example.com>',
614
                  author='John Doe <jdoe@example.com>')
615
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
616
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
617
        try:
618
            def trivial_custom_prop_handler(revision):
619
                return {'test_prop':'test_value'}
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
620
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
621
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
622
                'trivial_custom_prop_handler',
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
623
                trivial_custom_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
624
            log.show_log(b, formatter)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
625
        finally:
626
            log.properties_handler_registry.remove(
627
                'trivial_custom_prop_handler')
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
628
            self.assertEqualDiff('''\
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
629
------------------------------------------------------------
630
revno: 1
631
test_prop: test_value
632
author: John Doe <jdoe@example.com>
633
committer: Lorem Ipsum <test@example.com>
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
634
branch nick: test_properties_in_log
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
635
timestamp: Wed 2005-11-23 12:08:27 +1000
636
message:
637
  add a
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
638
''',
639
                                 sio.getvalue())
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
640
641
    def test_error_in_properties_handler(self):
642
        """Log includes the custom properties returned by the registered 
643
        handlers.
644
        """
645
        wt = self.make_branch_and_tree('.')
646
        b = wt.branch
647
        self.build_tree(['a'])
648
        wt.add('a')
649
        b.nick = 'test_author_log'
650
        wt.commit(message='add a',
651
                  timestamp=1132711707,
652
                  timezone=36000,
653
                  committer='Lorem Ipsum <test@example.com>',
654
                  author='John Doe <jdoe@example.com>',
655
                  revprops={'first_prop':'first_value'})
656
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
657
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
658
        try:
659
            def trivial_custom_prop_handler(revision):
660
                raise StandardError("a test error")
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
661
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
662
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
663
                'trivial_custom_prop_handler',
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
664
                trivial_custom_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
665
            self.assertRaises(StandardError, log.show_log, b, formatter,)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
666
        finally:
667
            log.properties_handler_registry.remove(
668
                'trivial_custom_prop_handler')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
669
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
670
    def test_properties_handler_bad_argument(self):
671
        wt = self.make_branch_and_tree('.')
672
        b = wt.branch
673
        self.build_tree(['a'])
674
        wt.add('a')
675
        b.nick = 'test_author_log'
676
        wt.commit(message='add a',
677
                  timestamp=1132711707,
678
                  timezone=36000,
679
                  committer='Lorem Ipsum <test@example.com>',
680
                  author='John Doe <jdoe@example.com>',
681
                  revprops={'a_prop':'test_value'})
682
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
683
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
684
        try:
685
            def bad_argument_prop_handler(revision):
686
                return {'custom_prop_name':revision.properties['a_prop']}
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
687
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
688
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
689
                'bad_argument_prop_handler',
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
690
                bad_argument_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
691
692
            self.assertRaises(AttributeError, formatter.show_properties,
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
693
                              'a revision', '')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
694
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
695
            revision = b.repository.get_revision(b.last_revision())
696
            formatter.show_properties(revision, '')
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
697
            self.assertEqualDiff('''custom_prop_name: test_value\n''',
698
                                 sio.getvalue())
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
699
        finally:
700
            log.properties_handler_registry.remove(
701
                'bad_argument_prop_handler')
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.
702
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
703
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
704
class TestLineLogFormatter(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
705
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
706
    def test_line_log(self):
707
        """Line log should show revno
708
        
709
        bug #5162
710
        """
711
        wt = self.make_branch_and_tree('.')
712
        b = wt.branch
713
        self.build_tree(['a'])
714
        wt.add('a')
715
        b.nick = 'test-line-log'
3642.1.5 by Robert Collins
Separate out batching of revisions.
716
        wt.commit(message='add a',
717
                  timestamp=1132711707,
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
718
                  timezone=36000,
719
                  committer='Line-Log-Formatter Tester <test@line.log>')
720
        logfile = file('out.tmp', 'w+')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
721
        formatter = log.LineLogFormatter(to_file=logfile)
722
        log.show_log(b, formatter)
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
723
        logfile.flush()
724
        logfile.seek(0)
725
        log_contents = logfile.read()
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
726
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
727
                             log_contents)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
728
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
729
    def test_trailing_newlines(self):
730
        wt = self.make_branch_and_tree('.')
731
        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.
732
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
733
        lf = log.LineLogFormatter(to_file=sio)
734
        log.show_log(b, lf)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
735
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
736
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.
737
2: Joe Bar 2005-11-21 multiline
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
738
1: Joe Foo 2005-11-21 simple log message
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
739
""",
740
                             sio.getvalue())
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
741
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
742
    def test_line_log_single_merge_revision(self):
743
        wt = self.make_branch_and_memory_tree('.')
744
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
745
        self.addCleanup(wt.unlock)
746
        wt.add('')
747
        wt.commit('rev-1', rev_id='rev-1',
748
                  timestamp=1132586655, timezone=36000,
749
                  committer='Joe Foo <joe@foo.com>')
750
        wt.commit('rev-merged', rev_id='rev-2a',
751
                  timestamp=1132586700, timezone=36000,
752
                  committer='Joe Foo <joe@foo.com>')
753
        wt.set_parent_ids(['rev-1', 'rev-2a'])
754
        wt.branch.set_last_revision_info(1, 'rev-1')
755
        wt.commit('rev-2', rev_id='rev-2b',
756
                  timestamp=1132586800, timezone=36000,
757
                  committer='Joe Foo <joe@foo.com>')
758
        logfile = self.make_utf8_encoded_stringio()
759
        formatter = log.LineLogFormatter(to_file=logfile)
760
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
761
        wtb = wt.branch
762
        rev = revspec.in_history(wtb)
763
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
764
        self.assertEqualDiff("""\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
765
1.1.1: Joe Foo 2005-11-22 rev-merged
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
766
""",
767
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
768
769
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
770
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
771
class TestGetViewRevisions(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
772
1756.2.22 by Aaron Bentley
Apply review comments
773
    def make_tree_with_commits(self):
774
        """Create a tree with well-known revision ids"""
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
775
        wt = self.make_branch_and_tree('tree1')
776
        wt.commit('commit one', rev_id='1')
777
        wt.commit('commit two', rev_id='2')
778
        wt.commit('commit three', rev_id='3')
779
        mainline_revs = [None, '1', '2', '3']
1756.2.22 by Aaron Bentley
Apply review comments
780
        rev_nos = {'1': 1, '2': 2, '3': 3}
781
        return mainline_revs, rev_nos, wt
782
783
    def make_tree_with_merges(self):
784
        """Create a tree with well-known revision ids and a merge"""
785
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
786
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
787
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
788
        wt.merge_from_branch(tree2.branch)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
789
        wt.commit('four-b', rev_id='4b')
790
        mainline_revs.append('4b')
1756.2.22 by Aaron Bentley
Apply review comments
791
        rev_nos['4b'] = 4
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
792
        # 4a: 3.1.1
1756.2.22 by Aaron Bentley
Apply review comments
793
        return mainline_revs, rev_nos, wt
794
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
795
    def make_tree_with_many_merges(self):
796
        """Create a tree with well-known revision ids"""
797
        wt = self.make_branch_and_tree('tree1')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
798
        self.build_tree_contents([('tree1/f', '1\n')])
799
        wt.add(['f'], ['f-id'])
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
800
        wt.commit('commit one', rev_id='1')
801
        wt.commit('commit two', rev_id='2')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
802
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
803
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
804
        self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
805
        tree3.commit('commit three a', rev_id='3a')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
806
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
807
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
808
        tree2.merge_from_branch(tree3.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
809
        tree2.commit('commit three b', rev_id='3b')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
810
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
811
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
812
        wt.commit('commit three c', rev_id='3c')
813
        tree2.commit('four-a', rev_id='4a')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
814
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
815
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
816
        wt.commit('four-b', rev_id='4b')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
817
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
818
        mainline_revs = [None, '1', '2', '3c', '4b']
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
819
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
820
        full_rev_nos_for_reference = {
821
            '1': '1',
822
            '2': '2',
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
823
            '3a': '2.1.1', #first commit tree 3
824
            '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,
825
            '3c': '3', #merges 3b to main
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
826
            '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,
827
            '4b': '4', # merges 4a to main
828
            }
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
829
        return mainline_revs, rev_nos, wt
830
1756.2.22 by Aaron Bentley
Apply review comments
831
    def test_get_view_revisions_forward(self):
832
        """Test the get_view_revisions method"""
833
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
834
        wt.lock_read()
835
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
836
        revisions = list(log.get_view_revisions(
837
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
838
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
839
                         revisions)
840
        revisions2 = list(log.get_view_revisions(
841
                mainline_revs, rev_nos, wt.branch, 'forward',
842
                include_merges=False))
1756.2.22 by Aaron Bentley
Apply review comments
843
        self.assertEqual(revisions, revisions2)
844
845
    def test_get_view_revisions_reverse(self):
846
        """Test the get_view_revisions with reverse"""
847
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
848
        wt.lock_read()
849
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
850
        revisions = list(log.get_view_revisions(
851
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
852
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
853
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
854
        revisions2 = list(log.get_view_revisions(
855
                mainline_revs, rev_nos, wt.branch, 'reverse',
856
                include_merges=False))
1756.2.22 by Aaron Bentley
Apply review comments
857
        self.assertEqual(revisions, revisions2)
858
859
    def test_get_view_revisions_merge(self):
860
        """Test get_view_revisions when there are merges"""
861
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
862
        wt.lock_read()
863
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
864
        revisions = list(log.get_view_revisions(
865
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
866
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
867
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
868
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
869
        revisions = list(log.get_view_revisions(
870
                mainline_revs, rev_nos, wt.branch, 'forward',
871
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
872
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
873
                          ('4b', '4', 0)],
874
                         revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
875
876
    def test_get_view_revisions_merge_reverse(self):
877
        """Test get_view_revisions in reverse when there are merges"""
878
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
879
        wt.lock_read()
880
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
881
        revisions = list(log.get_view_revisions(
882
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
883
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
884
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
885
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
886
        revisions = list(log.get_view_revisions(
887
                mainline_revs, rev_nos, wt.branch, 'reverse',
888
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
889
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
890
                          ('1', '1', 0)],
891
                         revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
892
893
    def test_get_view_revisions_merge2(self):
894
        """Test get_view_revisions when there are merges"""
895
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
896
        wt.lock_read()
897
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
898
        revisions = list(log.get_view_revisions(
899
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
900
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
901
                    ('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
902
                    ('4a', '2.2.2', 1)]
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
903
        self.assertEqual(expected, revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
904
        revisions = list(log.get_view_revisions(
905
                mainline_revs, rev_nos, wt.branch, 'forward',
906
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
907
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
908
                          ('4b', '4', 0)],
909
                         revisions)
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
910
911
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
912
    def test_file_id_for_range(self):
913
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
914
        wt.lock_read()
915
        self.addCleanup(wt.unlock)
916
917
        def rev_from_rev_id(revid, branch):
918
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
919
            return revspec.in_history(branch)
920
921
        def view_revs(start_rev, end_rev, file_id, direction):
922
            revs = log.calculate_view_revisions(
923
                wt.branch,
924
                start_rev, # start_revision
925
                end_rev, # end_revision
926
                direction, # direction
927
                file_id, # specific_fileid
928
                True, # generate_merge_revisions
929
                True, # allow_single_merge_revision
930
                )
931
            return revs
932
933
        rev_3a = rev_from_rev_id('3a', wt.branch)
934
        rev_4b = rev_from_rev_id('4b', wt.branch)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
935
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
936
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
937
        # there is still a bug somewhere... most probably in
938
        # _filter_revision_range and/or get_view_revisions still around a bad
939
        # use of reverse_by_depth
3936.3.7 by Ian Clatworthy
move fileid filtering up a layer
940
        self.assertEqual([('3a', '2.1.1', 1)],
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
941
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
942
943
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
944
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
945
946
    def create_tree_with_single_merge(self):
947
        """Create a branch with a moderate layout.
948
949
        The revision graph looks like:
950
951
           A
952
           |\
953
           B C
954
           |/
955
           D
956
957
        In this graph, A introduced files f1 and f2 and f3.
958
        B modifies f1 and f3, and C modifies f2 and f3.
959
        D merges the changes from B and C and resolves the conflict for f3.
960
        """
961
        # TODO: jam 20070218 This seems like it could really be done
962
        #       with make_branch_and_memory_tree() if we could just
963
        #       create the content of those files.
964
        # TODO: jam 20070218 Another alternative is that we would really
965
        #       like to only create this tree 1 time for all tests that
966
        #       use it. Since 'log' only uses the tree in a readonly
967
        #       fashion, it seems a shame to regenerate an identical
968
        #       tree for each test.
969
        tree = self.make_branch_and_tree('tree')
970
        tree.lock_write()
971
        self.addCleanup(tree.unlock)
972
973
        self.build_tree_contents([('tree/f1', 'A\n'),
974
                                  ('tree/f2', 'A\n'),
975
                                  ('tree/f3', 'A\n'),
976
                                 ])
977
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
978
        tree.commit('A', rev_id='A')
979
980
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
981
                                  ('tree/f3', 'A\nC\n'),
982
                                 ])
983
        tree.commit('C', rev_id='C')
984
        # Revert back to A to build the other history.
985
        tree.set_last_revision('A')
986
        tree.branch.set_last_revision_info(1, 'A')
987
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
988
                                  ('tree/f2', 'A\n'),
989
                                  ('tree/f3', 'A\nB\n'),
990
                                 ])
991
        tree.commit('B', rev_id='B')
992
        tree.set_parent_ids(['B', 'C'])
993
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
994
                                  ('tree/f2', 'A\nC\n'),
995
                                  ('tree/f3', 'A\nB\nC\n'),
996
                                 ])
997
        tree.commit('D', rev_id='D')
998
999
        # Switch to a read lock for this tree.
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1000
        # We still have an addCleanup(tree.unlock) pending
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1001
        tree.unlock()
1002
        tree.lock_read()
1003
        return tree
1004
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1005
    def check_delta(self, delta, **kw):
1006
        """Check the filenames touched by a delta are as expected.
1007
1008
        Caller only have to pass in the list of files for each part, all
1009
        unspecified parts are considered empty (and checked as such).
1010
        """
1011
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1012
            # By default we expect an empty list
1013
            expected = kw.get(n, [])
1014
            # strip out only the path components
1015
            got = [x[0] for x in getattr(delta, n)]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1016
            self.assertEqual(expected, got)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1017
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1018
    def test_tree_with_single_merge(self):
1019
        """Make sure the tree layout is correct."""
1020
        tree = self.create_tree_with_single_merge()
1021
        rev_A_tree = tree.branch.repository.revision_tree('A')
1022
        rev_B_tree = tree.branch.repository.revision_tree('B')
1023
        rev_C_tree = tree.branch.repository.revision_tree('C')
1024
        rev_D_tree = tree.branch.repository.revision_tree('D')
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1025
1026
        self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1027
                         modified=['f1', 'f3'])
1028
1029
        self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1030
                         modified=['f2', 'f3'])
1031
1032
        self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1033
                         modified=['f2', 'f3'])
1034
1035
        self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1036
                         modified=['f1', 'f3'])
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1037
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1038
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1039
        """Ensure _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
1040
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1041
        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
1042
        sure they are correct.
1043
        """
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1044
        # The api for _filter_revisions_touching_file_id is a little crazy.
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1045
        # So we do the setup here.
1046
        mainline = tree.branch.revision_history()
1047
        mainline.insert(0, None)
1048
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1049
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1050
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1051
        actual_revs = log._filter_revisions_touching_file_id(
3711.3.23 by John Arbash Meinel
Documentation and cleanup.
1052
                            tree.branch,
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1053
                            file_id,
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1054
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1055
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1056
1057
    def test_file_id_f1(self):
1058
        tree = self.create_tree_with_single_merge()
1059
        # f1 should be marked as modified by revisions A and B
1060
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1061
1062
    def test_file_id_f2(self):
1063
        tree = self.create_tree_with_single_merge()
1064
        # f2 should be marked as modified by revisions A, C, and D
1065
        # because D merged the changes from C.
1066
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1067
1068
    def test_file_id_f3(self):
1069
        tree = self.create_tree_with_single_merge()
1070
        # f3 should be marked as modified by revisions A, B, C, and D
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1071
        self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1072
3373.2.1 by John Arbash Meinel
Fix bug #209948, properly skip over ghosts when displaying the changes for a single file.
1073
    def test_file_id_with_ghosts(self):
1074
        # This is testing bug #209948, where having a ghost would cause
1075
        # _filter_revisions_touching_file_id() to fail.
1076
        tree = self.create_tree_with_single_merge()
1077
        # We need to add a revision, so switch back to a write-locked tree
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1078
        # (still a single addCleanup(tree.unlock) pending).
3373.2.1 by John Arbash Meinel
Fix bug #209948, properly skip over ghosts when displaying the changes for a single file.
1079
        tree.unlock()
1080
        tree.lock_write()
1081
        first_parent = tree.last_revision()
1082
        tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1083
        self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1084
        tree.commit('commit with a ghost', rev_id='XX')
1085
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1086
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1087
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1088
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1089
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1090
1091
    def test_show_changed_revisions_verbose(self):
1092
        tree = self.make_branch_and_tree('tree_a')
1093
        self.build_tree(['tree_a/foo'])
1094
        tree.add('foo')
1095
        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.
1096
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1097
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
1098
        self.assertContainsRe(s.getvalue(), 'bar')
1099
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1100
1101
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1102
class TestLogFormatter(tests.TestCase):
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1103
1104
    def test_short_committer(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1105
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1106
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1107
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1108
        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.
1109
        rev.committer = 'John Smith <jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1110
        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.
1111
        rev.committer = 'John Smith'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1112
        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.
1113
        rev.committer = 'jsmith@example.com'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1114
        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.
1115
        rev.committer = '<jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1116
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1117
        rev.committer = 'John Smith jsmith@example.com'
1118
        self.assertEqual('John Smith', lf.short_committer(rev))
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1119
1120
    def test_short_author(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1121
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1122
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1123
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1124
        self.assertEqual('John Doe', lf.short_author(rev))
1125
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
1126
        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.
1127
        rev.properties['author'] = 'John Smith'
1128
        self.assertEqual('John Smith', lf.short_author(rev))
1129
        rev.properties['author'] = 'jsmith@example.com'
1130
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
1131
        rev.properties['author'] = '<jsmith@example.com>'
1132
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1133
        rev.properties['author'] = 'John Smith jsmith@example.com'
1134
        self.assertEqual('John Smith', lf.short_author(rev))
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1135
1136
1137
class TestReverseByDepth(tests.TestCase):
1138
    """Test reverse_by_depth behavior.
1139
1140
    This is used to present revisions in forward (oldest first) order in a nice
1141
    layout.
1142
1143
    The tests use lighter revision description to ease reading.
1144
    """
1145
1146
    def assertReversed(self, forward, backward):
1147
        # Transform the descriptions to suit the API: tests use (revno, depth),
1148
        # while the API expects (revid, revno, depth)
1149
        def complete_revisions(l):
1150
            """Transform the description to suit the API.
1151
1152
            Tests use (revno, depth) whil the API expects (revid, revno, depth).
1153
            Since the revid is arbitrary, we just duplicate revno
1154
            """
1155
            return [ (r, r, d) for r, d in l]
1156
        forward = complete_revisions(forward)
1157
        backward= complete_revisions(backward)
1158
        self.assertEqual(forward, log.reverse_by_depth(backward))
1159
1160
1161
    def test_mainline_revisions(self):
1162
        self.assertReversed([( '1', 0), ('2', 0)],
1163
                            [('2', 0), ('1', 0)])
1164
1165
    def test_merged_revisions(self):
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1166
        self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1),],
1167
                            [('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0),])
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1168
    def test_shifted_merged_revisions(self):
1169
        """Test irregular layout.
1170
1171
        Requesting revisions touching a file can produce "holes" in the depths.
1172
        """
1173
        self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2),],
1174
                            [('2', 0), ('1.2', 2), ('1.1', 2), ('1', 0),])
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1175
1176
    def test_merged_without_child_revisions(self):
1177
        """Test irregular layout.
1178
1179
        Revision ranges can produce "holes" in the depths.
1180
        """
1181
        # When a revision of higher depth doesn't follow one of lower depth, we
1182
        # assume a lower depth one is virtually there
1183
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1184
                            [('4', 4), ('3', 3), ('2', 2), ('1', 2),])
1185
        # So we get the same order after reversing below even if the original
1186
        # revisions are not in the same order.
1187
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1188
                            [('3', 3), ('4', 4), ('2', 2), ('1', 2),])
3848.1.6 by Aaron Bentley
Implement get_history_change
1189
1190
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1191
class TestHistoryChange(tests.TestCaseWithTransport):
3848.1.6 by Aaron Bentley
Implement get_history_change
1192
1193
    def setup_a_tree(self):
1194
        tree = self.make_branch_and_tree('tree')
1195
        tree.lock_write()
1196
        self.addCleanup(tree.unlock)
1197
        tree.commit('1a', rev_id='1a')
1198
        tree.commit('2a', rev_id='2a')
1199
        tree.commit('3a', rev_id='3a')
1200
        return tree
1201
1202
    def setup_ab_tree(self):
1203
        tree = self.setup_a_tree()
1204
        tree.set_last_revision('1a')
1205
        tree.branch.set_last_revision_info(1, '1a')
1206
        tree.commit('2b', rev_id='2b')
1207
        tree.commit('3b', rev_id='3b')
1208
        return tree
1209
1210
    def setup_ac_tree(self):
1211
        tree = self.setup_a_tree()
1212
        tree.set_last_revision(revision.NULL_REVISION)
1213
        tree.branch.set_last_revision_info(0, revision.NULL_REVISION)
1214
        tree.commit('1c', rev_id='1c')
1215
        tree.commit('2c', rev_id='2c')
1216
        tree.commit('3c', rev_id='3c')
1217
        return tree
1218
1219
    def test_all_new(self):
1220
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1221
        old, new = log.get_history_change('1a', '3a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1222
        self.assertEqual([], old)
1223
        self.assertEqual(['2a', '3a'], new)
1224
1225
    def test_all_old(self):
1226
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1227
        old, new = log.get_history_change('3a', '1a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1228
        self.assertEqual([], new)
1229
        self.assertEqual(['2a', '3a'], old)
1230
1231
    def test_null_old(self):
1232
        tree = self.setup_ab_tree()
1233
        old, new = log.get_history_change(revision.NULL_REVISION,
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1234
                                          '3a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1235
        self.assertEqual([], old)
1236
        self.assertEqual(['1a', '2a', '3a'], new)
1237
1238
    def test_null_new(self):
1239
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1240
        old, new = log.get_history_change('3a', revision.NULL_REVISION,
1241
                                          tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1242
        self.assertEqual([], new)
1243
        self.assertEqual(['1a', '2a', '3a'], old)
1244
1245
    def test_diverged(self):
1246
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1247
        old, new = log.get_history_change('3a', '3b', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1248
        self.assertEqual(old, ['2a', '3a'])
1249
        self.assertEqual(new, ['2b', '3b'])
1250
1251
    def test_unrelated(self):
1252
        tree = self.setup_ac_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1253
        old, new = log.get_history_change('3a', '3c', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1254
        self.assertEqual(old, ['1a', '2a', '3a'])
1255
        self.assertEqual(new, ['1c', '2c', '3c'])
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1256
1257
    def test_show_branch_change(self):
1258
        tree = self.setup_ab_tree()
1259
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1260
        log.show_branch_change(tree.branch, s, 3, '3a')
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1261
        self.assertContainsRe(s.getvalue(),
1262
            '[*]{60}\nRemoved Revisions:\n(.|\n)*2a(.|\n)*3a(.|\n)*'
1263
            '[*]{60}\n\nAdded Revisions:\n(.|\n)*2b(.|\n)*3b')
1264
1265
    def test_show_branch_change_no_change(self):
1266
        tree = self.setup_ab_tree()
1267
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1268
        log.show_branch_change(tree.branch, s, 3, '3b')
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1269
        self.assertEqual(s.getvalue(),
1270
            'Nothing seems to have changed\n')
1271
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1272
    def test_show_branch_change_no_old(self):
1273
        tree = self.setup_ab_tree()
1274
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1275
        log.show_branch_change(tree.branch, s, 2, '2b')
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1276
        self.assertContainsRe(s.getvalue(), 'Added Revisions:')
1277
        self.assertNotContainsRe(s.getvalue(), 'Removed Revisions:')
1278
1279
    def test_show_branch_change_no_new(self):
1280
        tree = self.setup_ab_tree()
1281
        tree.branch.set_last_revision_info(2, '2b')
1282
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1283
        log.show_branch_change(tree.branch, s, 3, '3b')
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1284
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1285
        self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')