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