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