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