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