/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,
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
        # Note that the depth is 0 for 3a because depths are normalized, but
938
        # there is still a bug somewhere... most probably in
939
        # _filter_revision_range and/or get_view_revisions still around a bad
940
        # use of reverse_by_depth
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
941
        self.assertEqual([('3a', '2.1.1', 0)],
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
942
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
943
944
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
945
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
946
947
    def create_tree_with_single_merge(self):
948
        """Create a branch with a moderate layout.
949
950
        The revision graph looks like:
951
952
           A
953
           |\
954
           B C
955
           |/
956
           D
957
958
        In this graph, A introduced files f1 and f2 and f3.
959
        B modifies f1 and f3, and C modifies f2 and f3.
960
        D merges the changes from B and C and resolves the conflict for f3.
961
        """
962
        # TODO: jam 20070218 This seems like it could really be done
963
        #       with make_branch_and_memory_tree() if we could just
964
        #       create the content of those files.
965
        # TODO: jam 20070218 Another alternative is that we would really
966
        #       like to only create this tree 1 time for all tests that
967
        #       use it. Since 'log' only uses the tree in a readonly
968
        #       fashion, it seems a shame to regenerate an identical
969
        #       tree for each test.
970
        tree = self.make_branch_and_tree('tree')
971
        tree.lock_write()
972
        self.addCleanup(tree.unlock)
973
974
        self.build_tree_contents([('tree/f1', 'A\n'),
975
                                  ('tree/f2', 'A\n'),
976
                                  ('tree/f3', 'A\n'),
977
                                 ])
978
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
979
        tree.commit('A', rev_id='A')
980
981
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
982
                                  ('tree/f3', 'A\nC\n'),
983
                                 ])
984
        tree.commit('C', rev_id='C')
985
        # Revert back to A to build the other history.
986
        tree.set_last_revision('A')
987
        tree.branch.set_last_revision_info(1, 'A')
988
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
989
                                  ('tree/f2', 'A\n'),
990
                                  ('tree/f3', 'A\nB\n'),
991
                                 ])
992
        tree.commit('B', rev_id='B')
993
        tree.set_parent_ids(['B', 'C'])
994
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
995
                                  ('tree/f2', 'A\nC\n'),
996
                                  ('tree/f3', 'A\nB\nC\n'),
997
                                 ])
998
        tree.commit('D', rev_id='D')
999
1000
        # Switch to a read lock for this tree.
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1001
        # 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.
1002
        tree.unlock()
1003
        tree.lock_read()
1004
        return tree
1005
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1006
    def check_delta(self, delta, **kw):
1007
        """Check the filenames touched by a delta are as expected.
1008
1009
        Caller only have to pass in the list of files for each part, all
1010
        unspecified parts are considered empty (and checked as such).
1011
        """
1012
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1013
            # By default we expect an empty list
1014
            expected = kw.get(n, [])
1015
            # strip out only the path components
1016
            got = [x[0] for x in getattr(delta, n)]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1017
            self.assertEqual(expected, got)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1018
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1019
    def test_tree_with_single_merge(self):
1020
        """Make sure the tree layout is correct."""
1021
        tree = self.create_tree_with_single_merge()
1022
        rev_A_tree = tree.branch.repository.revision_tree('A')
1023
        rev_B_tree = tree.branch.repository.revision_tree('B')
1024
        rev_C_tree = tree.branch.repository.revision_tree('C')
1025
        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.
1026
1027
        self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1028
                         modified=['f1', 'f3'])
1029
1030
        self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1031
                         modified=['f2', 'f3'])
1032
1033
        self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1034
                         modified=['f2', 'f3'])
1035
1036
        self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1037
                         modified=['f1', 'f3'])
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1038
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1039
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1040
        """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
1041
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1042
        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
1043
        sure they are correct.
1044
        """
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1045
        # 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
1046
        # So we do the setup here.
1047
        mainline = tree.branch.revision_history()
1048
        mainline.insert(0, None)
1049
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1050
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1051
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1052
        actual_revs = log._filter_revisions_touching_file_id(
3711.3.23 by John Arbash Meinel
Documentation and cleanup.
1053
                            tree.branch,
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1054
                            file_id,
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1055
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1056
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1057
1058
    def test_file_id_f1(self):
1059
        tree = self.create_tree_with_single_merge()
1060
        # f1 should be marked as modified by revisions A and B
1061
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1062
1063
    def test_file_id_f2(self):
1064
        tree = self.create_tree_with_single_merge()
1065
        # f2 should be marked as modified by revisions A, C, and D
1066
        # because D merged the changes from C.
1067
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1068
1069
    def test_file_id_f3(self):
1070
        tree = self.create_tree_with_single_merge()
1071
        # 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.
1072
        self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1073
3373.2.1 by John Arbash Meinel
Fix bug #209948, properly skip over ghosts when displaying the changes for a single file.
1074
    def test_file_id_with_ghosts(self):
1075
        # This is testing bug #209948, where having a ghost would cause
1076
        # _filter_revisions_touching_file_id() to fail.
1077
        tree = self.create_tree_with_single_merge()
1078
        # 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.
1079
        # (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.
1080
        tree.unlock()
1081
        tree.lock_write()
1082
        first_parent = tree.last_revision()
1083
        tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1084
        self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1085
        tree.commit('commit with a ghost', rev_id='XX')
1086
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1087
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1088
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1089
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1090
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1091
1092
    def test_show_changed_revisions_verbose(self):
1093
        tree = self.make_branch_and_tree('tree_a')
1094
        self.build_tree(['tree_a/foo'])
1095
        tree.add('foo')
1096
        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.
1097
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1098
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
1099
        self.assertContainsRe(s.getvalue(), 'bar')
1100
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1101
1102
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1103
class TestLogFormatter(tests.TestCase):
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1104
1105
    def test_short_committer(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1106
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1107
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1108
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1109
        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.
1110
        rev.committer = 'John Smith <jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1111
        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.
1112
        rev.committer = 'John Smith'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1113
        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.
1114
        rev.committer = 'jsmith@example.com'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1115
        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.
1116
        rev.committer = '<jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1117
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1118
        rev.committer = 'John Smith jsmith@example.com'
1119
        self.assertEqual('John Smith', lf.short_committer(rev))
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1120
1121
    def test_short_author(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1122
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1123
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1124
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1125
        self.assertEqual('John Doe', lf.short_author(rev))
1126
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
1127
        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.
1128
        rev.properties['author'] = 'John Smith'
1129
        self.assertEqual('John Smith', lf.short_author(rev))
1130
        rev.properties['author'] = 'jsmith@example.com'
1131
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
1132
        rev.properties['author'] = '<jsmith@example.com>'
1133
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1134
        rev.properties['author'] = 'John Smith jsmith@example.com'
1135
        self.assertEqual('John Smith', lf.short_author(rev))
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1136
1137
1138
class TestReverseByDepth(tests.TestCase):
1139
    """Test reverse_by_depth behavior.
1140
1141
    This is used to present revisions in forward (oldest first) order in a nice
1142
    layout.
1143
1144
    The tests use lighter revision description to ease reading.
1145
    """
1146
1147
    def assertReversed(self, forward, backward):
1148
        # Transform the descriptions to suit the API: tests use (revno, depth),
1149
        # while the API expects (revid, revno, depth)
1150
        def complete_revisions(l):
1151
            """Transform the description to suit the API.
1152
1153
            Tests use (revno, depth) whil the API expects (revid, revno, depth).
1154
            Since the revid is arbitrary, we just duplicate revno
1155
            """
1156
            return [ (r, r, d) for r, d in l]
1157
        forward = complete_revisions(forward)
1158
        backward= complete_revisions(backward)
1159
        self.assertEqual(forward, log.reverse_by_depth(backward))
1160
1161
1162
    def test_mainline_revisions(self):
1163
        self.assertReversed([( '1', 0), ('2', 0)],
1164
                            [('2', 0), ('1', 0)])
1165
1166
    def test_merged_revisions(self):
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1167
        self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1),],
1168
                            [('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0),])
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1169
    def test_shifted_merged_revisions(self):
1170
        """Test irregular layout.
1171
1172
        Requesting revisions touching a file can produce "holes" in the depths.
1173
        """
1174
        self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2),],
1175
                            [('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.
1176
1177
    def test_merged_without_child_revisions(self):
1178
        """Test irregular layout.
1179
1180
        Revision ranges can produce "holes" in the depths.
1181
        """
1182
        # When a revision of higher depth doesn't follow one of lower depth, we
1183
        # assume a lower depth one is virtually there
1184
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1185
                            [('4', 4), ('3', 3), ('2', 2), ('1', 2),])
1186
        # So we get the same order after reversing below even if the original
1187
        # revisions are not in the same order.
1188
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1189
                            [('3', 3), ('4', 4), ('2', 2), ('1', 2),])
3848.1.6 by Aaron Bentley
Implement get_history_change
1190
1191
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1192
class TestHistoryChange(tests.TestCaseWithTransport):
3848.1.6 by Aaron Bentley
Implement get_history_change
1193
1194
    def setup_a_tree(self):
1195
        tree = self.make_branch_and_tree('tree')
1196
        tree.lock_write()
1197
        self.addCleanup(tree.unlock)
1198
        tree.commit('1a', rev_id='1a')
1199
        tree.commit('2a', rev_id='2a')
1200
        tree.commit('3a', rev_id='3a')
1201
        return tree
1202
1203
    def setup_ab_tree(self):
1204
        tree = self.setup_a_tree()
1205
        tree.set_last_revision('1a')
1206
        tree.branch.set_last_revision_info(1, '1a')
1207
        tree.commit('2b', rev_id='2b')
1208
        tree.commit('3b', rev_id='3b')
1209
        return tree
1210
1211
    def setup_ac_tree(self):
1212
        tree = self.setup_a_tree()
1213
        tree.set_last_revision(revision.NULL_REVISION)
1214
        tree.branch.set_last_revision_info(0, revision.NULL_REVISION)
1215
        tree.commit('1c', rev_id='1c')
1216
        tree.commit('2c', rev_id='2c')
1217
        tree.commit('3c', rev_id='3c')
1218
        return tree
1219
1220
    def test_all_new(self):
1221
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1222
        old, new = log.get_history_change('1a', '3a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1223
        self.assertEqual([], old)
1224
        self.assertEqual(['2a', '3a'], new)
1225
1226
    def test_all_old(self):
1227
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1228
        old, new = log.get_history_change('3a', '1a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1229
        self.assertEqual([], new)
1230
        self.assertEqual(['2a', '3a'], old)
1231
1232
    def test_null_old(self):
1233
        tree = self.setup_ab_tree()
1234
        old, new = log.get_history_change(revision.NULL_REVISION,
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1235
                                          '3a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1236
        self.assertEqual([], old)
1237
        self.assertEqual(['1a', '2a', '3a'], new)
1238
1239
    def test_null_new(self):
1240
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1241
        old, new = log.get_history_change('3a', revision.NULL_REVISION,
1242
                                          tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1243
        self.assertEqual([], new)
1244
        self.assertEqual(['1a', '2a', '3a'], old)
1245
1246
    def test_diverged(self):
1247
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1248
        old, new = log.get_history_change('3a', '3b', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1249
        self.assertEqual(old, ['2a', '3a'])
1250
        self.assertEqual(new, ['2b', '3b'])
1251
1252
    def test_unrelated(self):
1253
        tree = self.setup_ac_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1254
        old, new = log.get_history_change('3a', '3c', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1255
        self.assertEqual(old, ['1a', '2a', '3a'])
1256
        self.assertEqual(new, ['1c', '2c', '3c'])
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1257
1258
    def test_show_branch_change(self):
1259
        tree = self.setup_ab_tree()
1260
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1261
        log.show_branch_change(tree.branch, s, 3, '3a')
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1262
        self.assertContainsRe(s.getvalue(),
1263
            '[*]{60}\nRemoved Revisions:\n(.|\n)*2a(.|\n)*3a(.|\n)*'
1264
            '[*]{60}\n\nAdded Revisions:\n(.|\n)*2b(.|\n)*3b')
1265
1266
    def test_show_branch_change_no_change(self):
1267
        tree = self.setup_ab_tree()
1268
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1269
        log.show_branch_change(tree.branch, s, 3, '3b')
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1270
        self.assertEqual(s.getvalue(),
1271
            'Nothing seems to have changed\n')
1272
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1273
    def test_show_branch_change_no_old(self):
1274
        tree = self.setup_ab_tree()
1275
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1276
        log.show_branch_change(tree.branch, s, 2, '2b')
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1277
        self.assertContainsRe(s.getvalue(), 'Added Revisions:')
1278
        self.assertNotContainsRe(s.getvalue(), 'Removed Revisions:')
1279
1280
    def test_show_branch_change_no_new(self):
1281
        tree = self.setup_ab_tree()
1282
        tree.branch.set_last_revision_info(2, '2b')
1283
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1284
        log.show_branch_change(tree.branch, s, 3, '3b')
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1285
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1286
        self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')