/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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
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>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
243
              authors=['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
3946.3.2 by Ian Clatworthy
add tests & NEWS item
293
    def _prepare_tree_with_merges(self, with_tags=False):
294
        wt = self.make_branch_and_memory_tree('.')
295
        wt.lock_write()
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>')
304
        wt.set_parent_ids(['rev-1', 'rev-2a'])
305
        wt.branch.set_last_revision_info(1, 'rev-1')
306
        wt.commit('rev-2', rev_id='rev-2b',
307
                  timestamp=1132586800, timezone=36000,
308
                  committer='Joe Foo <joe@foo.com>')
309
        if with_tags:
310
            branch = wt.branch
311
            branch.tags.set_tag('v0.2', 'rev-2b')
312
            wt.commit('rev-3', rev_id='rev-3',
313
                      timestamp=1132586900, timezone=36000,
314
                      committer='Jane Foo <jane@foo.com>')
315
            branch.tags.set_tag('v1.0rc1', 'rev-3')
316
            branch.tags.set_tag('v1.0', 'rev-3')
317
        return wt
318
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
319
    def test_short_log_with_merges(self):
3946.3.2 by Ian Clatworthy
add tests & NEWS item
320
        wt = self._prepare_tree_with_merges()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
321
        logfile = self.make_utf8_encoded_stringio()
322
        formatter = log.ShortLogFormatter(to_file=logfile)
323
        log.show_log(wt.branch, formatter)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
324
        self.assertEqualDiff("""\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
325
    2 Joe Foo\t2005-11-22 [merge]
326
      rev-2
327
328
    1 Joe Foo\t2005-11-22
329
      rev-1
330
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
331
""",
332
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
333
3943.4.2 by John Arbash Meinel
Add a test case which exercises this code path.
334
    def test_short_log_with_merges_and_range(self):
335
        wt = self.make_branch_and_memory_tree('.')
336
        wt.lock_write()
337
        self.addCleanup(wt.unlock)
338
        wt.add('')
339
        wt.commit('rev-1', rev_id='rev-1',
340
                  timestamp=1132586655, timezone=36000,
341
                  committer='Joe Foo <joe@foo.com>')
342
        wt.commit('rev-merged', rev_id='rev-2a',
343
                  timestamp=1132586700, timezone=36000,
344
                  committer='Joe Foo <joe@foo.com>')
345
        wt.branch.set_last_revision_info(1, 'rev-1')
346
        wt.set_parent_ids(['rev-1', 'rev-2a'])
347
        wt.commit('rev-2b', rev_id='rev-2b',
348
                  timestamp=1132586800, timezone=36000,
349
                  committer='Joe Foo <joe@foo.com>')
350
        wt.commit('rev-3a', rev_id='rev-3a',
351
                  timestamp=1132586800, timezone=36000,
352
                  committer='Joe Foo <joe@foo.com>')
353
        wt.branch.set_last_revision_info(2, 'rev-2b')
354
        wt.set_parent_ids(['rev-2b', 'rev-3a'])
355
        wt.commit('rev-3b', rev_id='rev-3b',
356
                  timestamp=1132586800, timezone=36000,
357
                  committer='Joe Foo <joe@foo.com>')
358
        logfile = self.make_utf8_encoded_stringio()
359
        formatter = log.ShortLogFormatter(to_file=logfile)
360
        log.show_log(wt.branch, formatter,
361
            start_revision=2, end_revision=3)
362
        self.assertEqualDiff("""\
363
    3 Joe Foo\t2005-11-22 [merge]
364
      rev-3b
365
366
    2 Joe Foo\t2005-11-22 [merge]
367
      rev-2b
368
369
""",
370
                             logfile.getvalue())
371
3946.3.2 by Ian Clatworthy
add tests & NEWS item
372
    def test_short_log_with_tags(self):
373
        wt = self._prepare_tree_with_merges(with_tags=True)
374
        logfile = self.make_utf8_encoded_stringio()
375
        formatter = log.ShortLogFormatter(to_file=logfile)
376
        log.show_log(wt.branch, formatter)
377
        self.assertEqualDiff("""\
378
    3 Jane Foo\t2005-11-22 {v1.0, v1.0rc1}
379
      rev-3
380
381
    2 Joe Foo\t2005-11-22 {v0.2} [merge]
382
      rev-2
383
384
    1 Joe Foo\t2005-11-22
385
      rev-1
386
387
""",
388
                             logfile.getvalue())
389
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
390
    def test_short_log_single_merge_revision(self):
391
        wt = self.make_branch_and_memory_tree('.')
392
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
393
        self.addCleanup(wt.unlock)
394
        wt.add('')
395
        wt.commit('rev-1', rev_id='rev-1',
396
                  timestamp=1132586655, timezone=36000,
397
                  committer='Joe Foo <joe@foo.com>')
398
        wt.commit('rev-merged', rev_id='rev-2a',
399
                  timestamp=1132586700, timezone=36000,
400
                  committer='Joe Foo <joe@foo.com>')
401
        wt.set_parent_ids(['rev-1', 'rev-2a'])
402
        wt.branch.set_last_revision_info(1, 'rev-1')
403
        wt.commit('rev-2', rev_id='rev-2b',
404
                  timestamp=1132586800, timezone=36000,
405
                  committer='Joe Foo <joe@foo.com>')
406
        logfile = self.make_utf8_encoded_stringio()
407
        formatter = log.ShortLogFormatter(to_file=logfile)
408
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
409
        wtb = wt.branch
410
        rev = revspec.in_history(wtb)
411
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
412
        self.assertEqualDiff("""\
3947.1.10 by Ian Clatworthy
review feedback from vila
413
      1.1.1 Joe Foo\t2005-11-22
414
            rev-merged
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
415
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
416
""",
417
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
418
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
419
3947.1.2 by Ian Clatworthy
formatter tests
420
class TestShortLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
421
422
    def test_short_merge_revs_log_with_merges(self):
423
        wt = self.make_branch_and_memory_tree('.')
424
        wt.lock_write()
425
        self.addCleanup(wt.unlock)
426
        wt.add('')
427
        wt.commit('rev-1', rev_id='rev-1',
428
                  timestamp=1132586655, timezone=36000,
429
                  committer='Joe Foo <joe@foo.com>')
430
        wt.commit('rev-merged', rev_id='rev-2a',
431
                  timestamp=1132586700, timezone=36000,
432
                  committer='Joe Foo <joe@foo.com>')
433
        wt.set_parent_ids(['rev-1', 'rev-2a'])
434
        wt.branch.set_last_revision_info(1, 'rev-1')
435
        wt.commit('rev-2', rev_id='rev-2b',
436
                  timestamp=1132586800, timezone=36000,
437
                  committer='Joe Foo <joe@foo.com>')
438
        logfile = self.make_utf8_encoded_stringio()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
439
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
3947.1.2 by Ian Clatworthy
formatter tests
440
        log.show_log(wt.branch, formatter)
3947.1.7 by Ian Clatworthy
tweak indenting/offsetting for --short given dotted revno lengths
441
        # Note that the 1.1.1 indenting is in fact correct given that
442
        # the revision numbers are right justified within 5 characters
443
        # for mainline revnos and 9 characters for dotted revnos.
3947.1.2 by Ian Clatworthy
formatter tests
444
        self.assertEqualDiff("""\
445
    2 Joe Foo\t2005-11-22 [merge]
446
      rev-2
447
3947.1.10 by Ian Clatworthy
review feedback from vila
448
          1.1.1 Joe Foo\t2005-11-22
449
                rev-merged
3947.1.2 by Ian Clatworthy
formatter tests
450
451
    1 Joe Foo\t2005-11-22
452
      rev-1
453
454
""",
455
                             logfile.getvalue())
456
457
    def test_short_merge_revs_log_single_merge_revision(self):
458
        wt = self.make_branch_and_memory_tree('.')
459
        wt.lock_write()
460
        self.addCleanup(wt.unlock)
461
        wt.add('')
462
        wt.commit('rev-1', rev_id='rev-1',
463
                  timestamp=1132586655, timezone=36000,
464
                  committer='Joe Foo <joe@foo.com>')
465
        wt.commit('rev-merged', rev_id='rev-2a',
466
                  timestamp=1132586700, timezone=36000,
467
                  committer='Joe Foo <joe@foo.com>')
468
        wt.set_parent_ids(['rev-1', 'rev-2a'])
469
        wt.branch.set_last_revision_info(1, 'rev-1')
470
        wt.commit('rev-2', rev_id='rev-2b',
471
                  timestamp=1132586800, timezone=36000,
472
                  committer='Joe Foo <joe@foo.com>')
473
        logfile = self.make_utf8_encoded_stringio()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
474
        formatter = log.ShortLogFormatter(to_file=logfile, levels=0)
3947.1.2 by Ian Clatworthy
formatter tests
475
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
476
        wtb = wt.branch
477
        rev = revspec.in_history(wtb)
478
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
479
        self.assertEqualDiff("""\
3947.1.10 by Ian Clatworthy
review feedback from vila
480
      1.1.1 Joe Foo\t2005-11-22
481
            rev-merged
3947.1.2 by Ian Clatworthy
formatter tests
482
483
""",
484
                             logfile.getvalue())
485
486
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
487
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
488
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
489
    def test_verbose_log(self):
490
        """Verbose log includes changed files
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
491
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
492
        bug #4676
493
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
494
        wt = self.make_branch_and_tree('.')
495
        b = wt.branch
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
496
        self.build_tree(['a'])
1185.33.45 by Martin Pool
[merge] refactoring of branch vs working tree, etc (robertc)
497
        wt.add('a')
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
498
        # XXX: why does a longer nick show up?
499
        b.nick = 'test_verbose_log'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
500
        wt.commit(message='add a',
501
                  timestamp=1132711707,
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
502
                  timezone=36000,
503
                  committer='Lorem Ipsum <test@example.com>')
504
        logfile = file('out.tmp', 'w+')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
505
        formatter = log.LongLogFormatter(to_file=logfile)
506
        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)
507
        logfile.flush()
508
        logfile.seek(0)
509
        log_contents = logfile.read()
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
510
        self.assertEqualDiff('''\
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
511
------------------------------------------------------------
512
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
513
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)
514
branch nick: test_verbose_log
515
timestamp: Wed 2005-11-23 12:08:27 +1000
516
message:
517
  add a
518
added:
519
  a
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
520
''',
521
                             log_contents)
1185.85.4 by John Arbash Meinel
currently broken, trying to fix things up.
522
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
523
    def test_merges_are_indented_by_level(self):
524
        wt = self.make_branch_and_tree('parent')
525
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
526
        self.run_bzr('branch parent child')
527
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
528
        self.run_bzr('branch child smallerchild')
529
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
530
            'smallerchild'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
531
        os.chdir('child')
2581.1.6 by Martin Pool
fix up more run_bzr callers
532
        self.run_bzr('merge ../smallerchild')
533
        self.run_bzr(['commit', '-m', 'merge branch 2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
534
        os.chdir('../parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
535
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
536
        wt.commit('merge branch 1')
537
        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.
538
        sio = self.make_utf8_encoded_stringio()
4206.1.1 by Ian Clatworthy
log mainline by default
539
        lf = log.LongLogFormatter(to_file=sio, levels=0)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
540
        log.show_log(b, lf, verbose=True)
541
        the_log = normalize_log(sio.getvalue())
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
542
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
543
------------------------------------------------------------
4208.2.1 by Ian Clatworthy
merge indicators in log --long
544
revno: 2 [merge]
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
545
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
546
branch nick: parent
547
timestamp: Just now
548
message:
549
  merge branch 1
550
    ------------------------------------------------------------
4208.2.1 by Ian Clatworthy
merge indicators in log --long
551
    revno: 1.1.2 [merge]
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
552
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
553
    branch nick: child
554
    timestamp: Just now
555
    message:
556
      merge branch 2
557
        ------------------------------------------------------------
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
558
        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.
559
        committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
560
        branch nick: smallerchild
561
        timestamp: Just now
562
        message:
563
          branch 2
564
    ------------------------------------------------------------
565
    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.
566
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
567
    branch nick: child
568
    timestamp: Just now
569
    message:
570
      branch 1
571
------------------------------------------------------------
572
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
573
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
574
branch nick: parent
575
timestamp: Just now
576
message:
577
  first post
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
578
""",
579
                             the_log)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
580
581
    def test_verbose_merge_revisions_contain_deltas(self):
582
        wt = self.make_branch_and_tree('parent')
583
        self.build_tree(['parent/f1', 'parent/f2'])
584
        wt.add(['f1','f2'])
585
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
586
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
587
        os.unlink('child/f1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
588
        file('child/f2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
589
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
590
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
591
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
592
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
593
        wt.commit('merge branch 1')
594
        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.
595
        sio = self.make_utf8_encoded_stringio()
4206.1.1 by Ian Clatworthy
log mainline by default
596
        lf = log.LongLogFormatter(to_file=sio, levels=0)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
597
        log.show_log(b, lf, verbose=True)
598
        the_log = normalize_log(sio.getvalue())
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
599
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
600
------------------------------------------------------------
4208.2.1 by Ian Clatworthy
merge indicators in log --long
601
revno: 2 [merge]
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
602
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
603
branch nick: parent
604
timestamp: Just now
605
message:
606
  merge branch 1
607
removed:
608
  f1
609
modified:
610
  f2
611
    ------------------------------------------------------------
612
    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.
613
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
614
    branch nick: child
615
    timestamp: Just now
616
    message:
617
      removed f1 and modified f2
618
    removed:
619
      f1
620
    modified:
621
      f2
622
------------------------------------------------------------
623
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
624
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
625
branch nick: parent
626
timestamp: Just now
627
message:
628
  first post
629
added:
630
  f1
631
  f2
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
632
""",
633
                             the_log)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
634
635
    def test_trailing_newlines(self):
636
        wt = self.make_branch_and_tree('.')
637
        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.
638
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
639
        lf = log.LongLogFormatter(to_file=sio)
640
        log.show_log(b, lf)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
641
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
642
------------------------------------------------------------
643
revno: 3
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
644
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
645
branch nick: test
646
timestamp: Mon 2005-11-21 09:32:56 -0600
647
message:
648
  single line with trailing newline
649
------------------------------------------------------------
650
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.
651
author: Joe Bar <joe@bar.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
652
committer: Joe Foo <joe@foo.com>
653
branch nick: test
654
timestamp: Mon 2005-11-21 09:27:22 -0600
655
message:
656
  multiline
657
  log
658
  message
659
------------------------------------------------------------
660
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
661
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
662
branch nick: test
663
timestamp: Mon 2005-11-21 09:24:15 -0600
664
message:
665
  simple log message
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
666
""",
667
                             sio.getvalue())
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
668
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
669
    def test_author_in_log(self):
670
        """Log includes the author name if it's set in
671
        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.
672
        """
673
        wt = self.make_branch_and_tree('.')
674
        b = wt.branch
675
        self.build_tree(['a'])
676
        wt.add('a')
677
        b.nick = 'test_author_log'
678
        wt.commit(message='add a',
679
                  timestamp=1132711707,
680
                  timezone=36000,
681
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
682
                  authors=['John Doe <jdoe@example.com>',
683
                           'Jane Rey <jrey@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.
684
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
685
        formatter = log.LongLogFormatter(to_file=sio)
686
        log.show_log(b, formatter)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
687
        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.
688
------------------------------------------------------------
689
revno: 1
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
690
author: John Doe <jdoe@example.com>, Jane Rey <jrey@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.
691
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.
692
branch nick: test_author_log
693
timestamp: Wed 2005-11-23 12:08:27 +1000
694
message:
695
  add a
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
696
''',
697
                             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.
698
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
699
    def test_properties_in_log(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
700
        """Log includes the custom properties returned by the registered
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
701
        handlers.
702
        """
703
        wt = self.make_branch_and_tree('.')
704
        b = wt.branch
705
        self.build_tree(['a'])
706
        wt.add('a')
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
707
        b.nick = 'test_properties_in_log'
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
708
        wt.commit(message='add a',
709
                  timestamp=1132711707,
710
                  timezone=36000,
711
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
712
                  authors=['John Doe <jdoe@example.com>'])
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
713
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
714
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
715
        try:
716
            def trivial_custom_prop_handler(revision):
717
                return {'test_prop':'test_value'}
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
718
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
719
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
720
                'trivial_custom_prop_handler',
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
721
                trivial_custom_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
722
            log.show_log(b, formatter)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
723
        finally:
724
            log.properties_handler_registry.remove(
725
                'trivial_custom_prop_handler')
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
726
            self.assertEqualDiff('''\
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
727
------------------------------------------------------------
728
revno: 1
729
test_prop: test_value
730
author: John Doe <jdoe@example.com>
731
committer: Lorem Ipsum <test@example.com>
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
732
branch nick: test_properties_in_log
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
733
timestamp: Wed 2005-11-23 12:08:27 +1000
734
message:
735
  add a
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
736
''',
737
                                 sio.getvalue())
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
738
3976.3.1 by Neil Martinsen-Burrell
Add custom properties handling to short log format
739
    def test_properties_in_short_log(self):
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
740
        """Log includes the custom properties returned by the registered
3976.3.1 by Neil Martinsen-Burrell
Add custom properties handling to short log format
741
        handlers.
742
        """
743
        wt = self.make_branch_and_tree('.')
744
        b = wt.branch
745
        self.build_tree(['a'])
746
        wt.add('a')
747
        b.nick = 'test_properties_in_short_log'
748
        wt.commit(message='add a',
749
                  timestamp=1132711707,
750
                  timezone=36000,
751
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
752
                  authors=['John Doe <jdoe@example.com>'])
3976.3.1 by Neil Martinsen-Burrell
Add custom properties handling to short log format
753
        sio = StringIO()
754
        formatter = log.ShortLogFormatter(to_file=sio)
755
        try:
756
            def trivial_custom_prop_handler(revision):
757
                return {'test_prop':'test_value'}
758
759
            log.properties_handler_registry.register(
760
                'trivial_custom_prop_handler',
761
                trivial_custom_prop_handler)
762
            log.show_log(b, formatter)
763
        finally:
764
            log.properties_handler_registry.remove(
765
                'trivial_custom_prop_handler')
766
            self.assertEqualDiff('''\
3976.3.3 by Jelmer Vernooij
remove a tab character.
767
    1 John Doe\t2005-11-23
3976.3.1 by Neil Martinsen-Burrell
Add custom properties handling to short log format
768
      test_prop: test_value
769
      add a
770
771
''',
772
                                 sio.getvalue())
773
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
774
    def test_error_in_properties_handler(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
775
        """Log includes the custom properties returned by the registered
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
776
        handlers.
777
        """
778
        wt = self.make_branch_and_tree('.')
779
        b = wt.branch
780
        self.build_tree(['a'])
781
        wt.add('a')
782
        b.nick = 'test_author_log'
783
        wt.commit(message='add a',
784
                  timestamp=1132711707,
785
                  timezone=36000,
786
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
787
                  authors=['John Doe <jdoe@example.com>'],
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
788
                  revprops={'first_prop':'first_value'})
789
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
790
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
791
        try:
792
            def trivial_custom_prop_handler(revision):
793
                raise StandardError("a test error")
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
794
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
795
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
796
                'trivial_custom_prop_handler',
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
797
                trivial_custom_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
798
            self.assertRaises(StandardError, log.show_log, b, formatter,)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
799
        finally:
800
            log.properties_handler_registry.remove(
801
                'trivial_custom_prop_handler')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
802
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
803
    def test_properties_handler_bad_argument(self):
804
        wt = self.make_branch_and_tree('.')
805
        b = wt.branch
806
        self.build_tree(['a'])
807
        wt.add('a')
808
        b.nick = 'test_author_log'
809
        wt.commit(message='add a',
810
                  timestamp=1132711707,
811
                  timezone=36000,
812
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
813
                  authors=['John Doe <jdoe@example.com>'],
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
814
                  revprops={'a_prop':'test_value'})
815
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
816
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
817
        try:
818
            def bad_argument_prop_handler(revision):
819
                return {'custom_prop_name':revision.properties['a_prop']}
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
820
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
821
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
822
                'bad_argument_prop_handler',
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
823
                bad_argument_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
824
825
            self.assertRaises(AttributeError, formatter.show_properties,
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
826
                              'a revision', '')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
827
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
828
            revision = b.repository.get_revision(b.last_revision())
829
            formatter.show_properties(revision, '')
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
830
            self.assertEqualDiff('''custom_prop_name: test_value\n''',
831
                                 sio.getvalue())
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
832
        finally:
833
            log.properties_handler_registry.remove(
834
                '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.
835
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
836
3947.1.2 by Ian Clatworthy
formatter tests
837
class TestLongLogFormatterWithoutMergeRevisions(TestCaseWithoutPropsHandler):
838
839
    def test_long_verbose_log(self):
840
        """Verbose log includes changed files
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
841
3947.1.2 by Ian Clatworthy
formatter tests
842
        bug #4676
843
        """
844
        wt = self.make_branch_and_tree('.')
845
        b = wt.branch
846
        self.build_tree(['a'])
847
        wt.add('a')
848
        # XXX: why does a longer nick show up?
849
        b.nick = 'test_verbose_log'
850
        wt.commit(message='add a',
851
                  timestamp=1132711707,
852
                  timezone=36000,
853
                  committer='Lorem Ipsum <test@example.com>')
854
        logfile = file('out.tmp', 'w+')
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
855
        formatter = log.LongLogFormatter(to_file=logfile, levels=1)
3947.1.2 by Ian Clatworthy
formatter tests
856
        log.show_log(b, formatter, verbose=True)
857
        logfile.flush()
858
        logfile.seek(0)
859
        log_contents = logfile.read()
860
        self.assertEqualDiff('''\
861
------------------------------------------------------------
862
revno: 1
863
committer: Lorem Ipsum <test@example.com>
864
branch nick: test_verbose_log
865
timestamp: Wed 2005-11-23 12:08:27 +1000
866
message:
867
  add a
868
added:
869
  a
870
''',
871
                             log_contents)
872
873
    def test_long_verbose_contain_deltas(self):
874
        wt = self.make_branch_and_tree('parent')
875
        self.build_tree(['parent/f1', 'parent/f2'])
876
        wt.add(['f1','f2'])
877
        wt.commit('first post')
878
        self.run_bzr('branch parent child')
879
        os.unlink('child/f1')
880
        file('child/f2', 'wb').write('hello\n')
881
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
882
            'child'])
883
        os.chdir('parent')
884
        self.run_bzr('merge ../child')
885
        wt.commit('merge branch 1')
886
        b = wt.branch
887
        sio = self.make_utf8_encoded_stringio()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
888
        lf = log.LongLogFormatter(to_file=sio, levels=1)
3947.1.2 by Ian Clatworthy
formatter tests
889
        log.show_log(b, lf, verbose=True)
890
        the_log = normalize_log(sio.getvalue())
891
        self.assertEqualDiff("""\
892
------------------------------------------------------------
4208.2.1 by Ian Clatworthy
merge indicators in log --long
893
revno: 2 [merge]
3947.1.2 by Ian Clatworthy
formatter tests
894
committer: Lorem Ipsum <test@example.com>
895
branch nick: parent
896
timestamp: Just now
897
message:
898
  merge branch 1
899
removed:
900
  f1
901
modified:
902
  f2
903
------------------------------------------------------------
904
revno: 1
905
committer: Lorem Ipsum <test@example.com>
906
branch nick: parent
907
timestamp: Just now
908
message:
909
  first post
910
added:
911
  f1
912
  f2
4208.2.1 by Ian Clatworthy
merge indicators in log --long
913
------------------------------------------------------------
4208.2.2 by Ian Clatworthy
show --levels 0 in advice, not just -n0
914
Use --levels 0 (or -n0) to see merged revisions.
3947.1.2 by Ian Clatworthy
formatter tests
915
""",
916
                             the_log)
917
918
    def test_long_trailing_newlines(self):
919
        wt = self.make_branch_and_tree('.')
920
        b = make_commits_with_trailing_newlines(wt)
921
        sio = self.make_utf8_encoded_stringio()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
922
        lf = log.LongLogFormatter(to_file=sio, levels=1)
3947.1.2 by Ian Clatworthy
formatter tests
923
        log.show_log(b, lf)
924
        self.assertEqualDiff("""\
925
------------------------------------------------------------
926
revno: 3
927
committer: Joe Foo <joe@foo.com>
928
branch nick: test
929
timestamp: Mon 2005-11-21 09:32:56 -0600
930
message:
931
  single line with trailing newline
932
------------------------------------------------------------
933
revno: 2
934
author: Joe Bar <joe@bar.com>
935
committer: Joe Foo <joe@foo.com>
936
branch nick: test
937
timestamp: Mon 2005-11-21 09:27:22 -0600
938
message:
939
  multiline
940
  log
941
  message
942
------------------------------------------------------------
943
revno: 1
944
committer: Joe Foo <joe@foo.com>
945
branch nick: test
946
timestamp: Mon 2005-11-21 09:24:15 -0600
947
message:
948
  simple log message
949
""",
950
                             sio.getvalue())
951
952
    def test_long_author_in_log(self):
953
        """Log includes the author name if it's set in
954
        the revision properties
955
        """
956
        wt = self.make_branch_and_tree('.')
957
        b = wt.branch
958
        self.build_tree(['a'])
959
        wt.add('a')
960
        b.nick = 'test_author_log'
961
        wt.commit(message='add a',
962
                  timestamp=1132711707,
963
                  timezone=36000,
964
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
965
                  authors=['John Doe <jdoe@example.com>'])
3947.1.2 by Ian Clatworthy
formatter tests
966
        sio = StringIO()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
967
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
3947.1.2 by Ian Clatworthy
formatter tests
968
        log.show_log(b, formatter)
969
        self.assertEqualDiff('''\
970
------------------------------------------------------------
971
revno: 1
972
author: John Doe <jdoe@example.com>
973
committer: Lorem Ipsum <test@example.com>
974
branch nick: test_author_log
975
timestamp: Wed 2005-11-23 12:08:27 +1000
976
message:
977
  add a
978
''',
979
                             sio.getvalue())
980
981
    def test_long_properties_in_log(self):
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
982
        """Log includes the custom properties returned by the registered
3947.1.2 by Ian Clatworthy
formatter tests
983
        handlers.
984
        """
985
        wt = self.make_branch_and_tree('.')
986
        b = wt.branch
987
        self.build_tree(['a'])
988
        wt.add('a')
989
        b.nick = 'test_properties_in_log'
990
        wt.commit(message='add a',
991
                  timestamp=1132711707,
992
                  timezone=36000,
993
                  committer='Lorem Ipsum <test@example.com>',
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
994
                  authors=['John Doe <jdoe@example.com>'])
3947.1.2 by Ian Clatworthy
formatter tests
995
        sio = StringIO()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
996
        formatter = log.LongLogFormatter(to_file=sio, levels=1)
3947.1.2 by Ian Clatworthy
formatter tests
997
        try:
998
            def trivial_custom_prop_handler(revision):
999
                return {'test_prop':'test_value'}
1000
1001
            log.properties_handler_registry.register(
1002
                'trivial_custom_prop_handler',
1003
                trivial_custom_prop_handler)
1004
            log.show_log(b, formatter)
1005
        finally:
1006
            log.properties_handler_registry.remove(
1007
                'trivial_custom_prop_handler')
1008
            self.assertEqualDiff('''\
1009
------------------------------------------------------------
1010
revno: 1
1011
test_prop: test_value
1012
author: John Doe <jdoe@example.com>
1013
committer: Lorem Ipsum <test@example.com>
1014
branch nick: test_properties_in_log
1015
timestamp: Wed 2005-11-23 12:08:27 +1000
1016
message:
1017
  add a
1018
''',
1019
                                 sio.getvalue())
1020
1021
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1022
class TestLineLogFormatter(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1023
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
1024
    def test_line_log(self):
1025
        """Line log should show revno
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1026
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
1027
        bug #5162
1028
        """
1029
        wt = self.make_branch_and_tree('.')
1030
        b = wt.branch
1031
        self.build_tree(['a'])
1032
        wt.add('a')
1033
        b.nick = 'test-line-log'
3642.1.5 by Robert Collins
Separate out batching of revisions.
1034
        wt.commit(message='add a',
1035
                  timestamp=1132711707,
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
1036
                  timezone=36000,
1037
                  committer='Line-Log-Formatter Tester <test@line.log>')
1038
        logfile = file('out.tmp', 'w+')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1039
        formatter = log.LineLogFormatter(to_file=logfile)
1040
        log.show_log(b, formatter)
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
1041
        logfile.flush()
1042
        logfile.seek(0)
1043
        log_contents = logfile.read()
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1044
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1045
                             log_contents)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
1046
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1047
    def test_trailing_newlines(self):
1048
        wt = self.make_branch_and_tree('.')
1049
        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.
1050
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1051
        lf = log.LineLogFormatter(to_file=sio)
1052
        log.show_log(b, lf)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1053
        self.assertEqualDiff("""\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1054
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.
1055
2: Joe Bar 2005-11-21 multiline
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1056
1: Joe Foo 2005-11-21 simple log message
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1057
""",
1058
                             sio.getvalue())
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1059
3946.3.2 by Ian Clatworthy
add tests & NEWS item
1060
    def _prepare_tree_with_merges(self, with_tags=False):
1061
        wt = self.make_branch_and_memory_tree('.')
1062
        wt.lock_write()
1063
        self.addCleanup(wt.unlock)
1064
        wt.add('')
1065
        wt.commit('rev-1', rev_id='rev-1',
1066
                  timestamp=1132586655, timezone=36000,
1067
                  committer='Joe Foo <joe@foo.com>')
1068
        wt.commit('rev-merged', rev_id='rev-2a',
1069
                  timestamp=1132586700, timezone=36000,
1070
                  committer='Joe Foo <joe@foo.com>')
1071
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1072
        wt.branch.set_last_revision_info(1, 'rev-1')
1073
        wt.commit('rev-2', rev_id='rev-2b',
1074
                  timestamp=1132586800, timezone=36000,
1075
                  committer='Joe Foo <joe@foo.com>')
1076
        if with_tags:
1077
            branch = wt.branch
1078
            branch.tags.set_tag('v0.2', 'rev-2b')
1079
            wt.commit('rev-3', rev_id='rev-3',
1080
                      timestamp=1132586900, timezone=36000,
1081
                      committer='Jane Foo <jane@foo.com>')
1082
            branch.tags.set_tag('v1.0rc1', 'rev-3')
1083
            branch.tags.set_tag('v1.0', 'rev-3')
1084
        return wt
1085
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
1086
    def test_line_log_single_merge_revision(self):
3946.3.2 by Ian Clatworthy
add tests & NEWS item
1087
        wt = self._prepare_tree_with_merges()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1088
        logfile = self.make_utf8_encoded_stringio()
1089
        formatter = log.LineLogFormatter(to_file=logfile)
1090
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1091
        wtb = wt.branch
1092
        rev = revspec.in_history(wtb)
1093
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1094
        self.assertEqualDiff("""\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
1095
1.1.1: Joe Foo 2005-11-22 rev-merged
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1096
""",
1097
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
1098
3946.3.2 by Ian Clatworthy
add tests & NEWS item
1099
    def test_line_log_with_tags(self):
1100
        wt = self._prepare_tree_with_merges(with_tags=True)
1101
        logfile = self.make_utf8_encoded_stringio()
1102
        formatter = log.LineLogFormatter(to_file=logfile)
1103
        log.show_log(wt.branch, formatter)
1104
        self.assertEqualDiff("""\
3946.3.3 by Ian Clatworthy
feedback from jelmer re position of tags in --line
1105
3: Jane Foo 2005-11-22 {v1.0, v1.0rc1} rev-3
3983.2.1 by Neil Martinsen-Burrell
add merge indication to the line format
1106
2: Joe Foo 2005-11-22 [merge] {v0.2} rev-2
3946.3.2 by Ian Clatworthy
add tests & NEWS item
1107
1: Joe Foo 2005-11-22 rev-1
1108
""",
1109
                             logfile.getvalue())
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
1110
3947.1.2 by Ian Clatworthy
formatter tests
1111
class TestLineLogFormatterWithMergeRevisions(tests.TestCaseWithTransport):
1112
1113
    def test_line_merge_revs_log(self):
1114
        """Line log should show revno
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
1115
3947.1.2 by Ian Clatworthy
formatter tests
1116
        bug #5162
1117
        """
1118
        wt = self.make_branch_and_tree('.')
1119
        b = wt.branch
1120
        self.build_tree(['a'])
1121
        wt.add('a')
1122
        b.nick = 'test-line-log'
1123
        wt.commit(message='add a',
1124
                  timestamp=1132711707,
1125
                  timezone=36000,
1126
                  committer='Line-Log-Formatter Tester <test@line.log>')
1127
        logfile = file('out.tmp', 'w+')
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
1128
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
3947.1.2 by Ian Clatworthy
formatter tests
1129
        log.show_log(b, formatter)
1130
        logfile.flush()
1131
        logfile.seek(0)
1132
        log_contents = logfile.read()
1133
        self.assertEqualDiff('1: Line-Log-Formatte... 2005-11-23 add a\n',
1134
                             log_contents)
1135
1136
    def test_line_merge_revs_log_single_merge_revision(self):
1137
        wt = self.make_branch_and_memory_tree('.')
1138
        wt.lock_write()
1139
        self.addCleanup(wt.unlock)
1140
        wt.add('')
1141
        wt.commit('rev-1', rev_id='rev-1',
1142
                  timestamp=1132586655, timezone=36000,
1143
                  committer='Joe Foo <joe@foo.com>')
1144
        wt.commit('rev-merged', rev_id='rev-2a',
1145
                  timestamp=1132586700, timezone=36000,
1146
                  committer='Joe Foo <joe@foo.com>')
1147
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1148
        wt.branch.set_last_revision_info(1, 'rev-1')
1149
        wt.commit('rev-2', rev_id='rev-2b',
1150
                  timestamp=1132586800, timezone=36000,
1151
                  committer='Joe Foo <joe@foo.com>')
1152
        logfile = self.make_utf8_encoded_stringio()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
1153
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
3947.1.2 by Ian Clatworthy
formatter tests
1154
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
1155
        wtb = wt.branch
1156
        rev = revspec.in_history(wtb)
1157
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
1158
        self.assertEqualDiff("""\
1159
1.1.1: Joe Foo 2005-11-22 rev-merged
1160
""",
1161
                             logfile.getvalue())
1162
1163
    def test_line_merge_revs_log_with_merges(self):
1164
        wt = self.make_branch_and_memory_tree('.')
1165
        wt.lock_write()
1166
        self.addCleanup(wt.unlock)
1167
        wt.add('')
1168
        wt.commit('rev-1', rev_id='rev-1',
1169
                  timestamp=1132586655, timezone=36000,
1170
                  committer='Joe Foo <joe@foo.com>')
1171
        wt.commit('rev-merged', rev_id='rev-2a',
1172
                  timestamp=1132586700, timezone=36000,
1173
                  committer='Joe Foo <joe@foo.com>')
1174
        wt.set_parent_ids(['rev-1', 'rev-2a'])
1175
        wt.branch.set_last_revision_info(1, 'rev-1')
1176
        wt.commit('rev-2', rev_id='rev-2b',
1177
                  timestamp=1132586800, timezone=36000,
1178
                  committer='Joe Foo <joe@foo.com>')
1179
        logfile = self.make_utf8_encoded_stringio()
3947.1.6 by Ian Clatworthy
log -n/--level-count N option
1180
        formatter = log.LineLogFormatter(to_file=logfile, levels=0)
3947.1.2 by Ian Clatworthy
formatter tests
1181
        log.show_log(wt.branch, formatter)
1182
        self.assertEqualDiff("""\
3983.2.1 by Neil Martinsen-Burrell
add merge indication to the line format
1183
2: Joe Foo 2005-11-22 [merge] rev-2
3947.1.2 by Ian Clatworthy
formatter tests
1184
  1.1.1: Joe Foo 2005-11-22 rev-merged
1185
1: Joe Foo 2005-11-22 rev-1
1186
""",
1187
                             logfile.getvalue())
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1188
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1189
class TestGetViewRevisions(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
1190
1756.2.22 by Aaron Bentley
Apply review comments
1191
    def make_tree_with_commits(self):
1192
        """Create a tree with well-known revision ids"""
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
1193
        wt = self.make_branch_and_tree('tree1')
1194
        wt.commit('commit one', rev_id='1')
1195
        wt.commit('commit two', rev_id='2')
1196
        wt.commit('commit three', rev_id='3')
1197
        mainline_revs = [None, '1', '2', '3']
1756.2.22 by Aaron Bentley
Apply review comments
1198
        rev_nos = {'1': 1, '2': 2, '3': 3}
1199
        return mainline_revs, rev_nos, wt
1200
1201
    def make_tree_with_merges(self):
1202
        """Create a tree with well-known revision ids and a merge"""
1203
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
1204
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1205
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
1206
        wt.merge_from_branch(tree2.branch)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
1207
        wt.commit('four-b', rev_id='4b')
1208
        mainline_revs.append('4b')
1756.2.22 by Aaron Bentley
Apply review comments
1209
        rev_nos['4b'] = 4
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1210
        # 4a: 3.1.1
1756.2.22 by Aaron Bentley
Apply review comments
1211
        return mainline_revs, rev_nos, wt
1212
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1213
    def make_tree_with_many_merges(self):
1214
        """Create a tree with well-known revision ids"""
1215
        wt = self.make_branch_and_tree('tree1')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1216
        self.build_tree_contents([('tree1/f', '1\n')])
1217
        wt.add(['f'], ['f-id'])
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1218
        wt.commit('commit one', rev_id='1')
1219
        wt.commit('commit two', rev_id='2')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1220
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1221
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1222
        self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1223
        tree3.commit('commit three a', rev_id='3a')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1224
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1225
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
1226
        tree2.merge_from_branch(tree3.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1227
        tree2.commit('commit three b', rev_id='3b')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1228
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
1229
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1230
        wt.commit('commit three c', rev_id='3c')
1231
        tree2.commit('four-a', rev_id='4a')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1232
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
1233
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1234
        wt.commit('four-b', rev_id='4b')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1235
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1236
        mainline_revs = [None, '1', '2', '3c', '4b']
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1237
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
1238
        full_rev_nos_for_reference = {
1239
            '1': '1',
1240
            '2': '2',
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
1241
            '3a': '2.1.1', #first commit tree 3
1242
            '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,
1243
            '3c': '3', #merges 3b to main
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
1244
            '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,
1245
            '4b': '4', # merges 4a to main
1246
            }
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1247
        return mainline_revs, rev_nos, wt
1248
1756.2.22 by Aaron Bentley
Apply review comments
1249
    def test_get_view_revisions_forward(self):
1250
        """Test the get_view_revisions method"""
1251
        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.
1252
        wt.lock_read()
1253
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1254
        revisions = list(log.get_view_revisions(
1255
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1256
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1257
                         revisions)
1258
        revisions2 = list(log.get_view_revisions(
1259
                mainline_revs, rev_nos, wt.branch, 'forward',
1260
                include_merges=False))
1756.2.22 by Aaron Bentley
Apply review comments
1261
        self.assertEqual(revisions, revisions2)
1262
1263
    def test_get_view_revisions_reverse(self):
1264
        """Test the get_view_revisions with reverse"""
1265
        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.
1266
        wt.lock_read()
1267
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1268
        revisions = list(log.get_view_revisions(
1269
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1270
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1271
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1272
        revisions2 = list(log.get_view_revisions(
1273
                mainline_revs, rev_nos, wt.branch, 'reverse',
1274
                include_merges=False))
1756.2.22 by Aaron Bentley
Apply review comments
1275
        self.assertEqual(revisions, revisions2)
1276
1277
    def test_get_view_revisions_merge(self):
1278
        """Test get_view_revisions when there are merges"""
1279
        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.
1280
        wt.lock_read()
1281
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1282
        revisions = list(log.get_view_revisions(
1283
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1284
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1285
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
1286
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1287
        revisions = list(log.get_view_revisions(
1288
                mainline_revs, rev_nos, wt.branch, 'forward',
1289
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1290
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1291
                          ('4b', '4', 0)],
1292
                         revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1293
1294
    def test_get_view_revisions_merge_reverse(self):
1295
        """Test get_view_revisions in reverse when there are merges"""
1296
        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.
1297
        wt.lock_read()
1298
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1299
        revisions = list(log.get_view_revisions(
1300
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1301
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1302
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
1303
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1304
        revisions = list(log.get_view_revisions(
1305
                mainline_revs, rev_nos, wt.branch, 'reverse',
1306
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1307
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1308
                          ('1', '1', 0)],
1309
                         revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
1310
1311
    def test_get_view_revisions_merge2(self):
1312
        """Test get_view_revisions when there are merges"""
1313
        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.
1314
        wt.lock_read()
1315
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1316
        revisions = list(log.get_view_revisions(
1317
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1318
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1319
                    ('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
1320
                    ('4a', '2.2.2', 1)]
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1321
        self.assertEqual(expected, revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1322
        revisions = list(log.get_view_revisions(
1323
                mainline_revs, rev_nos, wt.branch, 'forward',
1324
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
1325
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1326
                          ('4b', '4', 0)],
1327
                         revisions)
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1328
1329
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1330
    def test_file_id_for_range(self):
1331
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
1332
        wt.lock_read()
1333
        self.addCleanup(wt.unlock)
1334
1335
        def rev_from_rev_id(revid, branch):
1336
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
1337
            return revspec.in_history(branch)
1338
1339
        def view_revs(start_rev, end_rev, file_id, direction):
1340
            revs = log.calculate_view_revisions(
1341
                wt.branch,
1342
                start_rev, # start_revision
1343
                end_rev, # end_revision
1344
                direction, # direction
1345
                file_id, # specific_fileid
1346
                True, # generate_merge_revisions
1347
                True, # allow_single_merge_revision
1348
                )
1349
            return revs
1350
1351
        rev_3a = rev_from_rev_id('3a', wt.branch)
1352
        rev_4b = rev_from_rev_id('4b', wt.branch)
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1353
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1354
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
3936.3.30 by Ian Clatworthy
use iter_merge_sorted_revisions() with stop_range feature
1355
        # Note: 3c still appears before 3a here because of depth-based sorting
1356
        self.assertEqual([('3c', '3', 0), ('3a', '2.1.1', 1)],
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1357
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
1358
1359
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1360
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1361
1362
    def create_tree_with_single_merge(self):
1363
        """Create a branch with a moderate layout.
1364
1365
        The revision graph looks like:
1366
1367
           A
1368
           |\
1369
           B C
1370
           |/
1371
           D
1372
1373
        In this graph, A introduced files f1 and f2 and f3.
1374
        B modifies f1 and f3, and C modifies f2 and f3.
1375
        D merges the changes from B and C and resolves the conflict for f3.
1376
        """
1377
        # TODO: jam 20070218 This seems like it could really be done
1378
        #       with make_branch_and_memory_tree() if we could just
1379
        #       create the content of those files.
1380
        # TODO: jam 20070218 Another alternative is that we would really
1381
        #       like to only create this tree 1 time for all tests that
1382
        #       use it. Since 'log' only uses the tree in a readonly
1383
        #       fashion, it seems a shame to regenerate an identical
1384
        #       tree for each test.
1385
        tree = self.make_branch_and_tree('tree')
1386
        tree.lock_write()
1387
        self.addCleanup(tree.unlock)
1388
1389
        self.build_tree_contents([('tree/f1', 'A\n'),
1390
                                  ('tree/f2', 'A\n'),
1391
                                  ('tree/f3', 'A\n'),
1392
                                 ])
1393
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
1394
        tree.commit('A', rev_id='A')
1395
1396
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
1397
                                  ('tree/f3', 'A\nC\n'),
1398
                                 ])
1399
        tree.commit('C', rev_id='C')
1400
        # Revert back to A to build the other history.
1401
        tree.set_last_revision('A')
1402
        tree.branch.set_last_revision_info(1, 'A')
1403
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
1404
                                  ('tree/f2', 'A\n'),
1405
                                  ('tree/f3', 'A\nB\n'),
1406
                                 ])
1407
        tree.commit('B', rev_id='B')
1408
        tree.set_parent_ids(['B', 'C'])
1409
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
1410
                                  ('tree/f2', 'A\nC\n'),
1411
                                  ('tree/f3', 'A\nB\nC\n'),
1412
                                 ])
1413
        tree.commit('D', rev_id='D')
1414
1415
        # Switch to a read lock for this tree.
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1416
        # 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.
1417
        tree.unlock()
1418
        tree.lock_read()
1419
        return tree
1420
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1421
    def check_delta(self, delta, **kw):
1422
        """Check the filenames touched by a delta are as expected.
1423
1424
        Caller only have to pass in the list of files for each part, all
1425
        unspecified parts are considered empty (and checked as such).
1426
        """
1427
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
1428
            # By default we expect an empty list
1429
            expected = kw.get(n, [])
1430
            # strip out only the path components
1431
            got = [x[0] for x in getattr(delta, n)]
3842.2.7 by Vincent Ladeuil
Fixed as per Jonh's review.
1432
            self.assertEqual(expected, got)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1433
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1434
    def test_tree_with_single_merge(self):
1435
        """Make sure the tree layout is correct."""
1436
        tree = self.create_tree_with_single_merge()
1437
        rev_A_tree = tree.branch.repository.revision_tree('A')
1438
        rev_B_tree = tree.branch.repository.revision_tree('B')
1439
        rev_C_tree = tree.branch.repository.revision_tree('C')
1440
        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.
1441
1442
        self.check_delta(rev_B_tree.changes_from(rev_A_tree),
1443
                         modified=['f1', 'f3'])
1444
1445
        self.check_delta(rev_C_tree.changes_from(rev_A_tree),
1446
                         modified=['f2', 'f3'])
1447
1448
        self.check_delta(rev_D_tree.changes_from(rev_B_tree),
1449
                         modified=['f2', 'f3'])
1450
1451
        self.check_delta(rev_D_tree.changes_from(rev_C_tree),
1452
                         modified=['f1', 'f3'])
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
1453
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1454
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1455
        """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
1456
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1457
        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
1458
        sure they are correct.
1459
        """
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1460
        # 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
1461
        # So we do the setup here.
1462
        mainline = tree.branch.revision_history()
1463
        mainline.insert(0, None)
1464
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
1465
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1466
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1467
        actual_revs = log._filter_revisions_touching_file_id(
3711.3.23 by John Arbash Meinel
Documentation and cleanup.
1468
                            tree.branch,
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1469
                            file_id,
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1470
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1471
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1472
1473
    def test_file_id_f1(self):
1474
        tree = self.create_tree_with_single_merge()
1475
        # f1 should be marked as modified by revisions A and B
1476
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1477
1478
    def test_file_id_f2(self):
1479
        tree = self.create_tree_with_single_merge()
1480
        # f2 should be marked as modified by revisions A, C, and D
1481
        # because D merged the changes from C.
1482
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1483
1484
    def test_file_id_f3(self):
1485
        tree = self.create_tree_with_single_merge()
1486
        # 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.
1487
        self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1488
3373.2.1 by John Arbash Meinel
Fix bug #209948, properly skip over ghosts when displaying the changes for a single file.
1489
    def test_file_id_with_ghosts(self):
1490
        # This is testing bug #209948, where having a ghost would cause
1491
        # _filter_revisions_touching_file_id() to fail.
1492
        tree = self.create_tree_with_single_merge()
1493
        # 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.
1494
        # (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.
1495
        tree.unlock()
1496
        tree.lock_write()
1497
        first_parent = tree.last_revision()
1498
        tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1499
        self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1500
        tree.commit('commit with a ghost', rev_id='XX')
1501
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1502
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1503
4183.3.1 by Vincent Ladeuil
Fix bug #346431 by allowing log._filter_revisions_touching_file_id to be
1504
    def test_unknown_file_id(self):
1505
        tree = self.create_tree_with_single_merge()
1506
        self.assertAllRevisionsForFileID(tree, 'unknown', [])
1507
1508
    def test_empty_branch_unknown_file_id(self):
1509
        tree = self.make_branch_and_tree('tree')
1510
        self.assertAllRevisionsForFileID(tree, 'unknown', [])
1511
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1512
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1513
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1514
1515
    def test_show_changed_revisions_verbose(self):
1516
        tree = self.make_branch_and_tree('tree_a')
1517
        self.build_tree(['tree_a/foo'])
1518
        tree.add('foo')
1519
        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.
1520
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1521
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
1522
        self.assertContainsRe(s.getvalue(), 'bar')
1523
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1524
1525
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1526
class TestLogFormatter(tests.TestCase):
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1527
1528
    def test_short_committer(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1529
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1530
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1531
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1532
        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.
1533
        rev.committer = 'John Smith <jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1534
        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.
1535
        rev.committer = 'John Smith'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1536
        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.
1537
        rev.committer = 'jsmith@example.com'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1538
        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.
1539
        rev.committer = '<jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1540
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1541
        rev.committer = 'John Smith jsmith@example.com'
1542
        self.assertEqual('John Smith', lf.short_committer(rev))
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1543
1544
    def test_short_author(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1545
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1546
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1547
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1548
        self.assertEqual('John Doe', lf.short_author(rev))
1549
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
1550
        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.
1551
        rev.properties['author'] = 'John Smith'
1552
        self.assertEqual('John Smith', lf.short_author(rev))
1553
        rev.properties['author'] = 'jsmith@example.com'
1554
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
1555
        rev.properties['author'] = '<jsmith@example.com>'
1556
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1557
        rev.properties['author'] = 'John Smith jsmith@example.com'
1558
        self.assertEqual('John Smith', lf.short_author(rev))
4056.2.3 by James Westby
Use a new "authors" revision property to allow multiple authors
1559
        del rev.properties['author']
1560
        rev.properties['authors'] = ('John Smith <jsmith@example.com>\n'
1561
                'Jane Rey <jrey@example.com>')
1562
        self.assertEqual('John Smith', lf.short_author(rev))
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1563
1564
1565
class TestReverseByDepth(tests.TestCase):
1566
    """Test reverse_by_depth behavior.
1567
1568
    This is used to present revisions in forward (oldest first) order in a nice
1569
    layout.
1570
1571
    The tests use lighter revision description to ease reading.
1572
    """
1573
1574
    def assertReversed(self, forward, backward):
1575
        # Transform the descriptions to suit the API: tests use (revno, depth),
1576
        # while the API expects (revid, revno, depth)
1577
        def complete_revisions(l):
1578
            """Transform the description to suit the API.
1579
1580
            Tests use (revno, depth) whil the API expects (revid, revno, depth).
1581
            Since the revid is arbitrary, we just duplicate revno
1582
            """
1583
            return [ (r, r, d) for r, d in l]
1584
        forward = complete_revisions(forward)
1585
        backward= complete_revisions(backward)
1586
        self.assertEqual(forward, log.reverse_by_depth(backward))
1587
1588
1589
    def test_mainline_revisions(self):
1590
        self.assertReversed([( '1', 0), ('2', 0)],
1591
                            [('2', 0), ('1', 0)])
1592
1593
    def test_merged_revisions(self):
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1594
        self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1),],
1595
                            [('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0),])
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1596
    def test_shifted_merged_revisions(self):
1597
        """Test irregular layout.
1598
1599
        Requesting revisions touching a file can produce "holes" in the depths.
1600
        """
1601
        self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2),],
1602
                            [('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.
1603
1604
    def test_merged_without_child_revisions(self):
1605
        """Test irregular layout.
1606
1607
        Revision ranges can produce "holes" in the depths.
1608
        """
1609
        # When a revision of higher depth doesn't follow one of lower depth, we
1610
        # assume a lower depth one is virtually there
1611
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1612
                            [('4', 4), ('3', 3), ('2', 2), ('1', 2),])
1613
        # So we get the same order after reversing below even if the original
1614
        # revisions are not in the same order.
1615
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1616
                            [('3', 3), ('4', 4), ('2', 2), ('1', 2),])
3848.1.6 by Aaron Bentley
Implement get_history_change
1617
1618
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1619
class TestHistoryChange(tests.TestCaseWithTransport):
3848.1.6 by Aaron Bentley
Implement get_history_change
1620
1621
    def setup_a_tree(self):
1622
        tree = self.make_branch_and_tree('tree')
1623
        tree.lock_write()
1624
        self.addCleanup(tree.unlock)
1625
        tree.commit('1a', rev_id='1a')
1626
        tree.commit('2a', rev_id='2a')
1627
        tree.commit('3a', rev_id='3a')
1628
        return tree
1629
1630
    def setup_ab_tree(self):
1631
        tree = self.setup_a_tree()
1632
        tree.set_last_revision('1a')
1633
        tree.branch.set_last_revision_info(1, '1a')
1634
        tree.commit('2b', rev_id='2b')
1635
        tree.commit('3b', rev_id='3b')
1636
        return tree
1637
1638
    def setup_ac_tree(self):
1639
        tree = self.setup_a_tree()
1640
        tree.set_last_revision(revision.NULL_REVISION)
1641
        tree.branch.set_last_revision_info(0, revision.NULL_REVISION)
1642
        tree.commit('1c', rev_id='1c')
1643
        tree.commit('2c', rev_id='2c')
1644
        tree.commit('3c', rev_id='3c')
1645
        return tree
1646
1647
    def test_all_new(self):
1648
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1649
        old, new = log.get_history_change('1a', '3a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1650
        self.assertEqual([], old)
1651
        self.assertEqual(['2a', '3a'], new)
1652
1653
    def test_all_old(self):
1654
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1655
        old, new = log.get_history_change('3a', '1a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1656
        self.assertEqual([], new)
1657
        self.assertEqual(['2a', '3a'], old)
1658
1659
    def test_null_old(self):
1660
        tree = self.setup_ab_tree()
1661
        old, new = log.get_history_change(revision.NULL_REVISION,
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1662
                                          '3a', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1663
        self.assertEqual([], old)
1664
        self.assertEqual(['1a', '2a', '3a'], new)
1665
1666
    def test_null_new(self):
1667
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1668
        old, new = log.get_history_change('3a', revision.NULL_REVISION,
1669
                                          tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1670
        self.assertEqual([], new)
1671
        self.assertEqual(['1a', '2a', '3a'], old)
1672
1673
    def test_diverged(self):
1674
        tree = self.setup_ab_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1675
        old, new = log.get_history_change('3a', '3b', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1676
        self.assertEqual(old, ['2a', '3a'])
1677
        self.assertEqual(new, ['2b', '3b'])
1678
1679
    def test_unrelated(self):
1680
        tree = self.setup_ac_tree()
3848.1.7 by Aaron Bentley
Use repository in get_history_change
1681
        old, new = log.get_history_change('3a', '3c', tree.branch.repository)
3848.1.6 by Aaron Bentley
Implement get_history_change
1682
        self.assertEqual(old, ['1a', '2a', '3a'])
1683
        self.assertEqual(new, ['1c', '2c', '3c'])
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1684
1685
    def test_show_branch_change(self):
1686
        tree = self.setup_ab_tree()
1687
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1688
        log.show_branch_change(tree.branch, s, 3, '3a')
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1689
        self.assertContainsRe(s.getvalue(),
1690
            '[*]{60}\nRemoved Revisions:\n(.|\n)*2a(.|\n)*3a(.|\n)*'
1691
            '[*]{60}\n\nAdded Revisions:\n(.|\n)*2b(.|\n)*3b')
1692
1693
    def test_show_branch_change_no_change(self):
1694
        tree = self.setup_ab_tree()
1695
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1696
        log.show_branch_change(tree.branch, s, 3, '3b')
3848.1.8 by Aaron Bentley
Implement basic show_branch_change
1697
        self.assertEqual(s.getvalue(),
1698
            'Nothing seems to have changed\n')
1699
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1700
    def test_show_branch_change_no_old(self):
1701
        tree = self.setup_ab_tree()
1702
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1703
        log.show_branch_change(tree.branch, s, 2, '2b')
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1704
        self.assertContainsRe(s.getvalue(), 'Added Revisions:')
1705
        self.assertNotContainsRe(s.getvalue(), 'Removed Revisions:')
1706
1707
    def test_show_branch_change_no_new(self):
1708
        tree = self.setup_ab_tree()
1709
        tree.branch.set_last_revision_info(2, '2b')
1710
        s = StringIO()
3848.1.12 by Aaron Bentley
Fix test parameter order
1711
        log.show_branch_change(tree.branch, s, 3, '3b')
3848.1.9 by Aaron Bentley
new/old sections are omitted as appropriate.
1712
        self.assertContainsRe(s.getvalue(), 'Removed Revisions:')
1713
        self.assertNotContainsRe(s.getvalue(), 'Added Revisions:')