/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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
import os
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
18
from cStringIO import StringIO
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
19
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
20
from bzrlib import (
21
    errors,
22
    log,
23
    registry,
24
    revision,
25
    revisionspec,
26
    tests,
27
    )
28
29
30
class TestCaseWithoutPropsHandler(tests.TestCaseWithTransport):
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
31
32
    def setUp(self):
33
        super(TestCaseWithoutPropsHandler, self).setUp()
34
        # keep a reference to the "current" custom prop. handler registry
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
35
        self.properties_handler_registry = log.properties_handler_registry
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
36
        # clean up the registry in log
37
        log.properties_handler_registry = registry.Registry()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
38
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
39
    def _cleanup(self):
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
40
        super(TestCaseWithoutPropsHandler, self)._cleanup()
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
41
        # restore the custom properties handler registry
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
42
        log.properties_handler_registry = self.properties_handler_registry
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
43
44
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
45
class LogCatcher(log.LogFormatter):
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
46
    """Pull log messages into list rather than displaying them.
47
48
    For ease of testing we save log messages here rather than actually
49
    formatting them, so that we can precisely check the result without
50
    being too dependent on the exact formatting.
51
52
    We should also test the LogFormatter.
53
    """
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
54
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
55
    supports_delta = True
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
56
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
57
    def __init__(self):
58
        super(LogCatcher, self).__init__(to_file=None)
59
        self.logs = []
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
60
2466.8.1 by Kent Gibson
Reworked LogFormatter API to simplify extending the attributes of the revision being logged. Added support for begin_log() and end_log() hooks in LogFormatters.
61
    def log_revision(self, revision):
62
        self.logs.append(revision)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
63
64
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
65
class TestShowLog(tests.TestCaseWithTransport):
1102 by Martin Pool
- merge test refactoring from robertc
66
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
67
    def checkDelta(self, delta, **kw):
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
68
        """Check the filenames touched by a delta are as expected.
69
70
        Caller only have to pass in the list of files for each part, all
71
        unspecified parts are considered empty (and checked as such).
72
        """
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
73
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
74
            # By default we expect an empty list
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
75
            expected = kw.get(n, [])
76
            # strip out only the path components
77
            got = [x[0] for x in getattr(delta, n)]
78
            self.assertEquals(expected, got)
79
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
80
    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.
81
        wt = self.make_branch_and_tree('.')
82
        b = wt.branch
1092.3.4 by Robert Collins
update symlink branch to integration
83
84
        lf = LogCatcher()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
85
        wt.commit('empty commit')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
86
        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.
87
88
        def assertInvalidRev(start, end):
89
            self.assertRaises(errors.InvalidRevisionNumber,
90
                              log.show_log, b, lf,
91
                              start_revision=start, end_revision=end)
92
93
        # Since there is a single revision in the branch all the combinations
94
        # below should fail.
95
        assertInvalidRev(2, 1)
96
        assertInvalidRev(1, 2)
97
        assertInvalidRev(0, 2)
98
        assertInvalidRev(1, 0)
99
        assertInvalidRev(-1, 1)
100
        assertInvalidRev(1, -1)
101
102
    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.
103
        wt = self.make_branch_and_tree('.')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
104
105
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
106
        log.show_log(wt.branch, lf)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
107
        # no entries yet
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
108
        self.assertEquals(lf.logs, [])
109
110
    def test_empty_commit(self):
111
        wt = self.make_branch_and_tree('.')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
112
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
113
        wt.commit('empty commit')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
114
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
115
        log.show_log(wt.branch, lf, verbose=True)
116
        self.assertEquals(len(lf.logs), 1)
117
        self.assertEquals(lf.logs[0].revno, '1')
118
        self.assertEquals(lf.logs[0].rev.message, 'empty commit')
119
        self.checkDelta(lf.logs[0].delta)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
120
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
121
    def test_simple_commit(self):
122
        wt = self.make_branch_and_tree('.')
123
        wt.commit('empty commit')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
124
        self.build_tree(['hello'])
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
125
        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.
126
        wt.commit('add one file',
127
                  committer=u'\u013d\xf3r\xe9m \xcdp\u0161\xfam '
128
                            u'<test@example.com>')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
129
        lf = LogCatcher()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
130
        log.show_log(wt.branch, lf, verbose=True)
131
        self.assertEquals(len(lf.logs), 2)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
132
        # first one is most recent
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
133
        log_entry = lf.logs[0]
134
        self.assertEquals(log_entry.revno, '2')
135
        self.assertEquals(log_entry.rev.message, 'add one file')
136
        self.checkDelta(log_entry.delta, added=['hello'])
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
137
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
138
    def test_commit_message_with_control_chars(self):
139
        wt = self.make_branch_and_tree('.')
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
140
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
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)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
144
        committed_msg = lf.logs[0].rev.message
145
        self.assert_(msg != committed_msg)
146
        self.assert_(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)
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
158
        committed_msg = lf.logs[0].rev.message
159
        self.assert_(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
        eq = self.assertEquals
164
        wt = self.make_branch_and_tree('parent')
165
        self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
166
        wt.add('file1')
167
        wt.add('file2')
168
        wt.commit(message='add file1 and file2')
2581.1.6 by Martin Pool
fix up more run_bzr callers
169
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
170
        os.unlink('child/file1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
171
        file('child/file2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
172
        self.run_bzr(['commit', '-m', 'remove file1 and modify file2',
173
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
174
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
175
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
176
        wt.commit('merge child branch')
177
        os.chdir('..')
178
        b = wt.branch
179
        lf = LogCatcher()
180
        lf.supports_merge_revisions = True
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
181
        log.show_log(b, lf, verbose=True)
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
182
        self.assertEquals(len(lf.logs),3)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
183
        logentry = lf.logs[0]
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
184
        self.assertEquals(logentry.revno, '2')
185
        self.assertEquals(logentry.rev.message, 'merge child branch')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
186
        d = logentry.delta
187
        self.checkDelta(d, removed=['file1'], modified=['file2'])
188
        logentry = lf.logs[1]
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
189
        self.assertEquals(logentry.revno, '1.1.1')
190
        self.assertEquals(logentry.rev.message, 'remove file1 and modify file2')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
191
        d = logentry.delta
192
        self.checkDelta(d, removed=['file1'], modified=['file2'])
193
        logentry = lf.logs[2]
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
194
        self.assertEquals(logentry.revno, '1')
195
        self.assertEquals(logentry.rev.message, 'add file1 and file2')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
196
        d = logentry.delta
197
        self.checkDelta(d, added=['file1', 'file2'])
198
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
199
    def test_merges_nonsupporting_formatter(self):
200
        """Tests that show_log will raise if the formatter doesn't
201
        support merge revisions."""
202
        wt = self.make_branch_and_memory_tree('.')
203
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
204
        self.addCleanup(wt.unlock)
205
        wt.add('')
206
        wt.commit('rev-1', rev_id='rev-1',
207
                  timestamp=1132586655, timezone=36000,
208
                  committer='Joe Foo <joe@foo.com>')
209
        wt.commit('rev-merged', rev_id='rev-2a',
210
                  timestamp=1132586700, timezone=36000,
211
                  committer='Joe Foo <joe@foo.com>')
212
        wt.set_parent_ids(['rev-1', 'rev-2a'])
213
        wt.branch.set_last_revision_info(1, 'rev-1')
214
        wt.commit('rev-2', rev_id='rev-2b',
215
                  timestamp=1132586800, timezone=36000,
216
                  committer='Joe Foo <joe@foo.com>')
217
        logfile = self.make_utf8_encoded_stringio()
218
        formatter = log.ShortLogFormatter(to_file=logfile)
219
        wtb = wt.branch
220
        lf = LogCatcher()
221
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
222
        rev = revspec.in_history(wtb)
223
        self.assertRaises(errors.BzrCommandError, log.show_log, wtb, lf,
224
                          start_revision=rev, end_revision=rev)
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
225
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
226
227
def make_commits_with_trailing_newlines(wt):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
228
    """Helper method for LogFormatter tests"""
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
229
    b = wt.branch
230
    b.nick='test'
231
    open('a', 'wb').write('hello moto\n')
232
    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.
233
    wt.commit('simple log message', rev_id='a1',
234
              timestamp=1132586655.459960938, timezone=-6*3600,
235
              committer='Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
236
    open('b', 'wb').write('goodbye\n')
237
    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.
238
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
239
              timestamp=1132586842.411175966, timezone=-6*3600,
240
              committer='Joe Foo <joe@foo.com>',
241
              author='Joe Bar <joe@bar.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
242
243
    open('c', 'wb').write('just another manic monday\n')
244
    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.
245
    wt.commit('single line with trailing newline\n', rev_id='a3',
246
              timestamp=1132587176.835228920, timezone=-6*3600,
247
              committer = 'Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
248
    return b
249
250
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
251
def normalize_log(log):
252
    """Replaces the variable lines of logs with fixed lines"""
253
    author = 'author: Dolor Sit <test@example.com>'
254
    committer = 'committer: Lorem Ipsum <test@example.com>'
255
    lines = log.splitlines(True)
256
    for idx,line in enumerate(lines):
257
        stripped_line = line.lstrip()
258
        indent = ' ' * (len(line) - len(stripped_line))
259
        if stripped_line.startswith('author:'):
260
            lines[idx] = indent + author + '\n'
261
        elif stripped_line.startswith('committer:'):
262
            lines[idx] = indent + committer + '\n'
263
        elif stripped_line.startswith('timestamp:'):
264
            lines[idx] = indent + 'timestamp: Just now\n'
265
    return ''.join(lines)
266
267
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
268
class TestShortLogFormatter(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
269
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
270
    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.
271
        wt = self.make_branch_and_tree('.')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
272
        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.
273
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
274
        lf = log.ShortLogFormatter(to_file=sio)
275
        log.show_log(b, lf)
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
276
        self.assertEqualDiff(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.
277
    3 Joe Foo\t2005-11-21
278
      single line with trailing newline
279
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.
280
    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.
281
      multiline
282
      log
283
      message
284
285
    1 Joe Foo\t2005-11-21
286
      simple log message
287
288
""")
289
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
290
    def test_short_log_with_merges(self):
291
        wt = self.make_branch_and_memory_tree('.')
292
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
293
        self.addCleanup(wt.unlock)
294
        wt.add('')
295
        wt.commit('rev-1', rev_id='rev-1',
296
                  timestamp=1132586655, timezone=36000,
297
                  committer='Joe Foo <joe@foo.com>')
298
        wt.commit('rev-merged', rev_id='rev-2a',
299
                  timestamp=1132586700, timezone=36000,
300
                  committer='Joe Foo <joe@foo.com>')
301
        wt.set_parent_ids(['rev-1', 'rev-2a'])
302
        wt.branch.set_last_revision_info(1, 'rev-1')
303
        wt.commit('rev-2', rev_id='rev-2b',
304
                  timestamp=1132586800, timezone=36000,
305
                  committer='Joe Foo <joe@foo.com>')
306
        logfile = self.make_utf8_encoded_stringio()
307
        formatter = log.ShortLogFormatter(to_file=logfile)
308
        log.show_log(wt.branch, formatter)
309
        self.assertEqualDiff(logfile.getvalue(), """\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
310
    2 Joe Foo\t2005-11-22 [merge]
311
      rev-2
312
313
    1 Joe Foo\t2005-11-22
314
      rev-1
315
316
""")
317
318
    def test_short_log_single_merge_revision(self):
319
        wt = self.make_branch_and_memory_tree('.')
320
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
321
        self.addCleanup(wt.unlock)
322
        wt.add('')
323
        wt.commit('rev-1', rev_id='rev-1',
324
                  timestamp=1132586655, timezone=36000,
325
                  committer='Joe Foo <joe@foo.com>')
326
        wt.commit('rev-merged', rev_id='rev-2a',
327
                  timestamp=1132586700, timezone=36000,
328
                  committer='Joe Foo <joe@foo.com>')
329
        wt.set_parent_ids(['rev-1', 'rev-2a'])
330
        wt.branch.set_last_revision_info(1, 'rev-1')
331
        wt.commit('rev-2', rev_id='rev-2b',
332
                  timestamp=1132586800, timezone=36000,
333
                  committer='Joe Foo <joe@foo.com>')
334
        logfile = self.make_utf8_encoded_stringio()
335
        formatter = log.ShortLogFormatter(to_file=logfile)
336
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
337
        wtb = wt.branch
338
        rev = revspec.in_history(wtb)
339
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
340
        self.assertEqualDiff(logfile.getvalue(), """\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
341
1.1.1 Joe Foo\t2005-11-22
342
      rev-merged
343
344
""")
345
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
346
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
347
class TestLongLogFormatter(TestCaseWithoutPropsHandler):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
348
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
349
    def test_verbose_log(self):
350
        """Verbose log includes changed files
351
        
352
        bug #4676
353
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
354
        wt = self.make_branch_and_tree('.')
355
        b = wt.branch
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
356
        self.build_tree(['a'])
1185.33.45 by Martin Pool
[merge] refactoring of branch vs working tree, etc (robertc)
357
        wt.add('a')
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
358
        # XXX: why does a longer nick show up?
359
        b.nick = 'test_verbose_log'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
360
        wt.commit(message='add a',
361
                  timestamp=1132711707,
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
362
                  timezone=36000,
363
                  committer='Lorem Ipsum <test@example.com>')
364
        logfile = file('out.tmp', 'w+')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
365
        formatter = log.LongLogFormatter(to_file=logfile)
366
        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)
367
        logfile.flush()
368
        logfile.seek(0)
369
        log_contents = logfile.read()
370
        self.assertEqualDiff(log_contents, '''\
371
------------------------------------------------------------
372
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
373
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)
374
branch nick: test_verbose_log
375
timestamp: Wed 2005-11-23 12:08:27 +1000
376
message:
377
  add a
378
added:
379
  a
380
''')
1185.85.4 by John Arbash Meinel
currently broken, trying to fix things up.
381
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
382
    def test_merges_are_indented_by_level(self):
383
        wt = self.make_branch_and_tree('parent')
384
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
385
        self.run_bzr('branch parent child')
386
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
387
        self.run_bzr('branch child smallerchild')
388
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
389
            'smallerchild'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
390
        os.chdir('child')
2581.1.6 by Martin Pool
fix up more run_bzr callers
391
        self.run_bzr('merge ../smallerchild')
392
        self.run_bzr(['commit', '-m', 'merge branch 2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
393
        os.chdir('../parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
394
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
395
        wt.commit('merge branch 1')
396
        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.
397
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
398
        lf = log.LongLogFormatter(to_file=sio)
399
        log.show_log(b, lf, verbose=True)
400
        the_log = normalize_log(sio.getvalue())
401
        self.assertEqualDiff(the_log, """\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
402
------------------------------------------------------------
403
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
404
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
405
branch nick: parent
406
timestamp: Just now
407
message:
408
  merge branch 1
409
    ------------------------------------------------------------
410
    revno: 1.1.2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
411
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
412
    branch nick: child
413
    timestamp: Just now
414
    message:
415
      merge branch 2
416
        ------------------------------------------------------------
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
417
        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.
418
        committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
419
        branch nick: smallerchild
420
        timestamp: Just now
421
        message:
422
          branch 2
423
    ------------------------------------------------------------
424
    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.
425
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
426
    branch nick: child
427
    timestamp: Just now
428
    message:
429
      branch 1
430
------------------------------------------------------------
431
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
432
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
433
branch nick: parent
434
timestamp: Just now
435
message:
436
  first post
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
437
""")
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
438
439
    def test_verbose_merge_revisions_contain_deltas(self):
440
        wt = self.make_branch_and_tree('parent')
441
        self.build_tree(['parent/f1', 'parent/f2'])
442
        wt.add(['f1','f2'])
443
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
444
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
445
        os.unlink('child/f1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
446
        file('child/f2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
447
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
448
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
449
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
450
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
451
        wt.commit('merge branch 1')
452
        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.
453
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
454
        lf = log.LongLogFormatter(to_file=sio)
455
        log.show_log(b, lf, verbose=True)
456
        the_log = normalize_log(sio.getvalue())
457
        self.assertEqualDiff(the_log, """\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
458
------------------------------------------------------------
459
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
460
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
461
branch nick: parent
462
timestamp: Just now
463
message:
464
  merge branch 1
465
removed:
466
  f1
467
modified:
468
  f2
469
    ------------------------------------------------------------
470
    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.
471
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
472
    branch nick: child
473
    timestamp: Just now
474
    message:
475
      removed f1 and modified f2
476
    removed:
477
      f1
478
    modified:
479
      f2
480
------------------------------------------------------------
481
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
482
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
483
branch nick: parent
484
timestamp: Just now
485
message:
486
  first post
487
added:
488
  f1
489
  f2
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
490
""")
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
491
492
    def test_trailing_newlines(self):
493
        wt = self.make_branch_and_tree('.')
494
        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.
495
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
496
        lf = log.LongLogFormatter(to_file=sio)
497
        log.show_log(b, lf)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
498
        self.assertEqualDiff(sio.getvalue(), """\
499
------------------------------------------------------------
500
revno: 3
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
501
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
502
branch nick: test
503
timestamp: Mon 2005-11-21 09:32:56 -0600
504
message:
505
  single line with trailing newline
506
------------------------------------------------------------
507
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.
508
author: Joe Bar <joe@bar.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
509
committer: Joe Foo <joe@foo.com>
510
branch nick: test
511
timestamp: Mon 2005-11-21 09:27:22 -0600
512
message:
513
  multiline
514
  log
515
  message
516
------------------------------------------------------------
517
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
518
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
519
branch nick: test
520
timestamp: Mon 2005-11-21 09:24:15 -0600
521
message:
522
  simple log message
523
""")
524
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
525
    def test_author_in_log(self):
526
        """Log includes the author name if it's set in
527
        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.
528
        """
529
        wt = self.make_branch_and_tree('.')
530
        b = wt.branch
531
        self.build_tree(['a'])
532
        wt.add('a')
533
        b.nick = 'test_author_log'
534
        wt.commit(message='add a',
535
                  timestamp=1132711707,
536
                  timezone=36000,
537
                  committer='Lorem Ipsum <test@example.com>',
2671.2.5 by Lukáš Lalinský
Fixes for comments from the mailing list.
538
                  author='John Doe <jdoe@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.
539
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
540
        formatter = log.LongLogFormatter(to_file=sio)
541
        log.show_log(b, formatter)
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.
542
        self.assertEqualDiff(sio.getvalue(), '''\
543
------------------------------------------------------------
544
revno: 1
545
author: John Doe <jdoe@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.
546
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.
547
branch nick: test_author_log
548
timestamp: Wed 2005-11-23 12:08:27 +1000
549
message:
550
  add a
551
''')
552
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
553
    def test_properties_in_log(self):
554
        """Log includes the custom properties returned by the registered 
555
        handlers.
556
        """
557
        wt = self.make_branch_and_tree('.')
558
        b = wt.branch
559
        self.build_tree(['a'])
560
        wt.add('a')
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
561
        b.nick = 'test_properties_in_log'
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
562
        wt.commit(message='add a',
563
                  timestamp=1132711707,
564
                  timezone=36000,
565
                  committer='Lorem Ipsum <test@example.com>',
566
                  author='John Doe <jdoe@example.com>')
567
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
568
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
569
        try:
570
            def trivial_custom_prop_handler(revision):
571
                return {'test_prop':'test_value'}
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
572
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
573
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
574
                'trivial_custom_prop_handler',
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
575
                trivial_custom_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
576
            log.show_log(b, formatter)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
577
        finally:
578
            log.properties_handler_registry.remove(
579
                'trivial_custom_prop_handler')
580
            self.assertEqualDiff(sio.getvalue(), '''\
581
------------------------------------------------------------
582
revno: 1
583
test_prop: test_value
584
author: John Doe <jdoe@example.com>
585
committer: Lorem Ipsum <test@example.com>
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
586
branch nick: test_properties_in_log
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
587
timestamp: Wed 2005-11-23 12:08:27 +1000
588
message:
589
  add a
590
''')
591
592
    def test_error_in_properties_handler(self):
593
        """Log includes the custom properties returned by the registered 
594
        handlers.
595
        """
596
        wt = self.make_branch_and_tree('.')
597
        b = wt.branch
598
        self.build_tree(['a'])
599
        wt.add('a')
600
        b.nick = 'test_author_log'
601
        wt.commit(message='add a',
602
                  timestamp=1132711707,
603
                  timezone=36000,
604
                  committer='Lorem Ipsum <test@example.com>',
605
                  author='John Doe <jdoe@example.com>',
606
                  revprops={'first_prop':'first_value'})
607
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
608
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
609
        try:
610
            def trivial_custom_prop_handler(revision):
611
                raise StandardError("a test error")
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
612
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
613
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
614
                'trivial_custom_prop_handler',
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
615
                trivial_custom_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
616
            self.assertRaises(StandardError, log.show_log, b, formatter,)
3144.7.9 by Guillermo Gonzalez
* bzrlib.log.show_roperties don't hide handler errors
617
        finally:
618
            log.properties_handler_registry.remove(
619
                'trivial_custom_prop_handler')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
620
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
621
    def test_properties_handler_bad_argument(self):
622
        wt = self.make_branch_and_tree('.')
623
        b = wt.branch
624
        self.build_tree(['a'])
625
        wt.add('a')
626
        b.nick = 'test_author_log'
627
        wt.commit(message='add a',
628
                  timestamp=1132711707,
629
                  timezone=36000,
630
                  committer='Lorem Ipsum <test@example.com>',
631
                  author='John Doe <jdoe@example.com>',
632
                  revprops={'a_prop':'test_value'})
633
        sio = StringIO()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
634
        formatter = log.LongLogFormatter(to_file=sio)
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
635
        try:
636
            def bad_argument_prop_handler(revision):
637
                return {'custom_prop_name':revision.properties['a_prop']}
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
638
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
639
            log.properties_handler_registry.register(
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
640
                'bad_argument_prop_handler',
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
641
                bad_argument_prop_handler)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
642
643
            self.assertRaises(AttributeError, formatter.show_properties,
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
644
                'a revision', '')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
645
3144.7.13 by Guillermo Gonzalez
* fixed typo LogFormatter.show_properties in docstring
646
            revision = b.repository.get_revision(b.last_revision())
647
            formatter.show_properties(revision, '')
648
            self.assertEqualDiff(sio.getvalue(),
649
                '''custom_prop_name: test_value\n''')
650
        finally:
651
            log.properties_handler_registry.remove(
652
                '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.
653
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
654
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
655
class TestLineLogFormatter(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
656
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
657
    def test_line_log(self):
658
        """Line log should show revno
659
        
660
        bug #5162
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-line-log'
3642.1.5 by Robert Collins
Separate out batching of revisions.
667
        wt.commit(message='add a',
668
                  timestamp=1132711707,
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
669
                  timezone=36000,
670
                  committer='Line-Log-Formatter Tester <test@line.log>')
671
        logfile = file('out.tmp', 'w+')
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
672
        formatter = log.LineLogFormatter(to_file=logfile)
673
        log.show_log(b, formatter)
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
674
        logfile.flush()
675
        logfile.seek(0)
676
        log_contents = logfile.read()
2978.6.2 by Kent Gibson
When comparing logs using assertEqualDiff, pass the igenerated log first then the expected log so the output reflects what is additional in or missing from the generated log.
677
        self.assertEqualDiff(log_contents,
678
            '1: Line-Log-Formatte... 2005-11-23 add a\n')
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
679
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
680
    def test_trailing_newlines(self):
681
        wt = self.make_branch_and_tree('.')
682
        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.
683
        sio = self.make_utf8_encoded_stringio()
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
684
        lf = log.LineLogFormatter(to_file=sio)
685
        log.show_log(b, lf)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
686
        self.assertEqualDiff(sio.getvalue(), """\
687
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.
688
2: Joe Bar 2005-11-21 multiline
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
689
1: Joe Foo 2005-11-21 simple log message
690
""")
691
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
692
    def test_line_log_single_merge_revision(self):
693
        wt = self.make_branch_and_memory_tree('.')
694
        wt.lock_write()
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
695
        self.addCleanup(wt.unlock)
696
        wt.add('')
697
        wt.commit('rev-1', rev_id='rev-1',
698
                  timestamp=1132586655, timezone=36000,
699
                  committer='Joe Foo <joe@foo.com>')
700
        wt.commit('rev-merged', rev_id='rev-2a',
701
                  timestamp=1132586700, timezone=36000,
702
                  committer='Joe Foo <joe@foo.com>')
703
        wt.set_parent_ids(['rev-1', 'rev-2a'])
704
        wt.branch.set_last_revision_info(1, 'rev-1')
705
        wt.commit('rev-2', rev_id='rev-2b',
706
                  timestamp=1132586800, timezone=36000,
707
                  committer='Joe Foo <joe@foo.com>')
708
        logfile = self.make_utf8_encoded_stringio()
709
        formatter = log.LineLogFormatter(to_file=logfile)
710
        revspec = revisionspec.RevisionSpec.from_string('1.1.1')
711
        wtb = wt.branch
712
        rev = revspec.in_history(wtb)
713
        log.show_log(wtb, formatter, start_revision=rev, end_revision=rev)
714
        self.assertEqualDiff(logfile.getvalue(), """\
2997.1.1 by Kent Gibson
Support logging single merge revisions with short and line log formatters.
715
1.1.1: Joe Foo 2005-11-22 rev-merged
716
""")
717
718
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
719
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
720
class TestGetViewRevisions(tests.TestCaseWithTransport):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
721
1756.2.22 by Aaron Bentley
Apply review comments
722
    def make_tree_with_commits(self):
723
        """Create a tree with well-known revision ids"""
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
724
        wt = self.make_branch_and_tree('tree1')
725
        wt.commit('commit one', rev_id='1')
726
        wt.commit('commit two', rev_id='2')
727
        wt.commit('commit three', rev_id='3')
728
        mainline_revs = [None, '1', '2', '3']
1756.2.22 by Aaron Bentley
Apply review comments
729
        rev_nos = {'1': 1, '2': 2, '3': 3}
730
        return mainline_revs, rev_nos, wt
731
732
    def make_tree_with_merges(self):
733
        """Create a tree with well-known revision ids and a merge"""
734
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
735
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
736
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
737
        wt.merge_from_branch(tree2.branch)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
738
        wt.commit('four-b', rev_id='4b')
739
        mainline_revs.append('4b')
1756.2.22 by Aaron Bentley
Apply review comments
740
        rev_nos['4b'] = 4
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
741
        # 4a: 3.1.1
1756.2.22 by Aaron Bentley
Apply review comments
742
        return mainline_revs, rev_nos, wt
743
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
744
    def make_tree_with_many_merges(self):
745
        """Create a tree with well-known revision ids"""
746
        wt = self.make_branch_and_tree('tree1')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
747
        self.build_tree_contents([('tree1/f', '1\n')])
748
        wt.add(['f'], ['f-id'])
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
749
        wt.commit('commit one', rev_id='1')
750
        wt.commit('commit two', rev_id='2')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
751
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
752
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
753
        self.build_tree_contents([('tree3/f', '1\n2\n3a\n')])
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
754
        tree3.commit('commit three a', rev_id='3a')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
755
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
756
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
757
        tree2.merge_from_branch(tree3.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
758
        tree2.commit('commit three b', rev_id='3b')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
759
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
760
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
761
        wt.commit('commit three c', rev_id='3c')
762
        tree2.commit('four-a', rev_id='4a')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
763
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
764
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
765
        wt.commit('four-b', rev_id='4b')
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
766
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
767
        mainline_revs = [None, '1', '2', '3c', '4b']
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
768
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
769
        full_rev_nos_for_reference = {
770
            '1': '1',
771
            '2': '2',
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
772
            '3a': '2.1.1', #first commit tree 3
773
            '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,
774
            '3c': '3', #merges 3b to main
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
775
            '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,
776
            '4b': '4', # merges 4a to main
777
            }
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
778
        return mainline_revs, rev_nos, wt
779
1756.2.22 by Aaron Bentley
Apply review comments
780
    def test_get_view_revisions_forward(self):
781
        """Test the get_view_revisions method"""
782
        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.
783
        wt.lock_read()
784
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
785
        revisions = list(log.get_view_revisions(
786
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
787
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
788
                         revisions)
789
        revisions2 = list(log.get_view_revisions(
790
                mainline_revs, rev_nos, wt.branch, 'forward',
791
                include_merges=False))
1756.2.22 by Aaron Bentley
Apply review comments
792
        self.assertEqual(revisions, revisions2)
793
794
    def test_get_view_revisions_reverse(self):
795
        """Test the get_view_revisions with reverse"""
796
        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.
797
        wt.lock_read()
798
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
799
        revisions = list(log.get_view_revisions(
800
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
801
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
802
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
803
        revisions2 = list(log.get_view_revisions(
804
                mainline_revs, rev_nos, wt.branch, 'reverse',
805
                include_merges=False))
1756.2.22 by Aaron Bentley
Apply review comments
806
        self.assertEqual(revisions, revisions2)
807
808
    def test_get_view_revisions_merge(self):
809
        """Test get_view_revisions when there are merges"""
810
        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.
811
        wt.lock_read()
812
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
813
        revisions = list(log.get_view_revisions(
814
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
815
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
816
                          ('4b', '4', 0), ('4a', '3.1.1', 1)],
817
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
818
        revisions = list(log.get_view_revisions(
819
                mainline_revs, rev_nos, wt.branch, 'forward',
820
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
821
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
822
                          ('4b', '4', 0)],
823
                         revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
824
825
    def test_get_view_revisions_merge_reverse(self):
826
        """Test get_view_revisions in reverse when there are merges"""
827
        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.
828
        wt.lock_read()
829
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
830
        revisions = list(log.get_view_revisions(
831
                mainline_revs, rev_nos, wt.branch, 'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
832
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
833
                          ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
834
                         revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
835
        revisions = list(log.get_view_revisions(
836
                mainline_revs, rev_nos, wt.branch, 'reverse',
837
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
838
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
839
                          ('1', '1', 0)],
840
                         revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
841
842
    def test_get_view_revisions_merge2(self):
843
        """Test get_view_revisions when there are merges"""
844
        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.
845
        wt.lock_read()
846
        self.addCleanup(wt.unlock)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
847
        revisions = list(log.get_view_revisions(
848
                mainline_revs, rev_nos, wt.branch, 'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
849
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
850
                    ('3a', '2.1.1', 1), ('3b', '2.2.1', 1), ('4b', '4', 0),
851
                    ('4a', '2.2.2', 1)]
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
852
        self.assertEqual(expected, revisions)
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
853
        revisions = list(log.get_view_revisions(
854
                mainline_revs, rev_nos, wt.branch, 'forward',
855
                include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
856
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
857
                          ('4b', '4', 0)],
858
                         revisions)
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
859
860
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
861
    def test_file_id_for_range(self):
862
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
863
        wt.lock_read()
864
        self.addCleanup(wt.unlock)
865
866
        def rev_from_rev_id(revid, branch):
867
            revspec = revisionspec.RevisionSpec.from_string('revid:%s' % revid)
868
            return revspec.in_history(branch)
869
870
        def view_revs(start_rev, end_rev, file_id, direction):
871
            revs = log.calculate_view_revisions(
872
                wt.branch,
873
                start_rev, # start_revision
874
                end_rev, # end_revision
875
                direction, # direction
876
                file_id, # specific_fileid
877
                True, # generate_merge_revisions
878
                True, # allow_single_merge_revision
879
                )
880
            return revs
881
882
        rev_3a = rev_from_rev_id('3a', wt.branch)
883
        rev_4b = rev_from_rev_id('4b', wt.branch)
884
        self.assertEquals([('3c', '3', 0), ('3a', '2.1.1', 1)],
885
                          view_revs(rev_3a, rev_4b, 'f-id', 'reverse'))
886
        # Note that the depth is 0 for 3a because depths are normalized, but
887
        # there is still a bug somewhere... most probably in
888
        # _filter_revision_range and/or get_view_revisions still around a bad
889
        # use of reverse_by_depth
890
        self.assertEquals([('3a', '2.1.1', 0)],
891
                          view_revs(rev_3a, rev_4b, 'f-id', 'forward'))
892
893
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
894
class TestGetRevisionsTouchingFileID(tests.TestCaseWithTransport):
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
895
896
    def create_tree_with_single_merge(self):
897
        """Create a branch with a moderate layout.
898
899
        The revision graph looks like:
900
901
           A
902
           |\
903
           B C
904
           |/
905
           D
906
907
        In this graph, A introduced files f1 and f2 and f3.
908
        B modifies f1 and f3, and C modifies f2 and f3.
909
        D merges the changes from B and C and resolves the conflict for f3.
910
        """
911
        # TODO: jam 20070218 This seems like it could really be done
912
        #       with make_branch_and_memory_tree() if we could just
913
        #       create the content of those files.
914
        # TODO: jam 20070218 Another alternative is that we would really
915
        #       like to only create this tree 1 time for all tests that
916
        #       use it. Since 'log' only uses the tree in a readonly
917
        #       fashion, it seems a shame to regenerate an identical
918
        #       tree for each test.
919
        tree = self.make_branch_and_tree('tree')
920
        tree.lock_write()
921
        self.addCleanup(tree.unlock)
922
923
        self.build_tree_contents([('tree/f1', 'A\n'),
924
                                  ('tree/f2', 'A\n'),
925
                                  ('tree/f3', 'A\n'),
926
                                 ])
927
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
928
        tree.commit('A', rev_id='A')
929
930
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
931
                                  ('tree/f3', 'A\nC\n'),
932
                                 ])
933
        tree.commit('C', rev_id='C')
934
        # Revert back to A to build the other history.
935
        tree.set_last_revision('A')
936
        tree.branch.set_last_revision_info(1, 'A')
937
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
938
                                  ('tree/f2', 'A\n'),
939
                                  ('tree/f3', 'A\nB\n'),
940
                                 ])
941
        tree.commit('B', rev_id='B')
942
        tree.set_parent_ids(['B', 'C'])
943
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
944
                                  ('tree/f2', 'A\nC\n'),
945
                                  ('tree/f3', 'A\nB\nC\n'),
946
                                 ])
947
        tree.commit('D', rev_id='D')
948
949
        # Switch to a read lock for this tree.
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
950
        # 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.
951
        tree.unlock()
952
        tree.lock_read()
953
        return tree
954
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
955
    def check_delta(self, delta, **kw):
956
        """Check the filenames touched by a delta are as expected.
957
958
        Caller only have to pass in the list of files for each part, all
959
        unspecified parts are considered empty (and checked as such).
960
        """
961
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
962
            # By default we expect an empty list
963
            expected = kw.get(n, [])
964
            # strip out only the path components
965
            got = [x[0] for x in getattr(delta, n)]
966
            self.assertEquals(expected, got)
967
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
968
    def test_tree_with_single_merge(self):
969
        """Make sure the tree layout is correct."""
970
        tree = self.create_tree_with_single_merge()
971
        rev_A_tree = tree.branch.repository.revision_tree('A')
972
        rev_B_tree = tree.branch.repository.revision_tree('B')
973
        rev_C_tree = tree.branch.repository.revision_tree('C')
974
        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.
975
976
        self.check_delta(rev_B_tree.changes_from(rev_A_tree),
977
                         modified=['f1', 'f3'])
978
979
        self.check_delta(rev_C_tree.changes_from(rev_A_tree),
980
                         modified=['f2', 'f3'])
981
982
        self.check_delta(rev_D_tree.changes_from(rev_B_tree),
983
                         modified=['f2', 'f3'])
984
985
        self.check_delta(rev_D_tree.changes_from(rev_C_tree),
986
                         modified=['f1', 'f3'])
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
987
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
988
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
989
        """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
990
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
991
        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
992
        sure they are correct.
993
        """
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
994
        # 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
995
        # So we do the setup here.
996
        mainline = tree.branch.revision_history()
997
        mainline.insert(0, None)
998
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
999
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
1000
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1001
        actual_revs = log._filter_revisions_touching_file_id(
3711.3.23 by John Arbash Meinel
Documentation and cleanup.
1002
                            tree.branch,
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
1003
                            file_id,
3842.2.5 by Vincent Ladeuil
Better fix for bug #300055.
1004
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
1005
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
1006
1007
    def test_file_id_f1(self):
1008
        tree = self.create_tree_with_single_merge()
1009
        # f1 should be marked as modified by revisions A and B
1010
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
1011
1012
    def test_file_id_f2(self):
1013
        tree = self.create_tree_with_single_merge()
1014
        # f2 should be marked as modified by revisions A, C, and D
1015
        # because D merged the changes from C.
1016
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1017
1018
    def test_file_id_f3(self):
1019
        tree = self.create_tree_with_single_merge()
1020
        # 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.
1021
        self.assertAllRevisionsForFileID(tree, 'f3-id', ['D', 'C', 'B', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1022
3373.2.1 by John Arbash Meinel
Fix bug #209948, properly skip over ghosts when displaying the changes for a single file.
1023
    def test_file_id_with_ghosts(self):
1024
        # This is testing bug #209948, where having a ghost would cause
1025
        # _filter_revisions_touching_file_id() to fail.
1026
        tree = self.create_tree_with_single_merge()
1027
        # 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.
1028
        # (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.
1029
        tree.unlock()
1030
        tree.lock_write()
1031
        first_parent = tree.last_revision()
1032
        tree.set_parent_ids([first_parent, 'ghost-revision-id'])
1033
        self.build_tree_contents([('tree/f1', 'A\nB\nXX\n')])
1034
        tree.commit('commit with a ghost', rev_id='XX')
1035
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['XX', 'B', 'A'])
1036
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1037
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1038
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1039
class TestShowChangedRevisions(tests.TestCaseWithTransport):
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1040
1041
    def test_show_changed_revisions_verbose(self):
1042
        tree = self.make_branch_and_tree('tree_a')
1043
        self.build_tree(['tree_a/foo'])
1044
        tree.add('foo')
1045
        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.
1046
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
1047
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
1048
        self.assertContainsRe(s.getvalue(), 'bar')
1049
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1050
1051
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1052
class TestLogFormatter(tests.TestCase):
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1053
1054
    def test_short_committer(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1055
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1056
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1057
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1058
        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.
1059
        rev.committer = 'John Smith <jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1060
        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.
1061
        rev.committer = 'John Smith'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1062
        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.
1063
        rev.committer = 'jsmith@example.com'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1064
        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.
1065
        rev.committer = '<jsmith@example.com>'
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1066
        self.assertEqual('jsmith@example.com', lf.short_committer(rev))
1067
        rev.committer = 'John Smith jsmith@example.com'
1068
        self.assertEqual('John Smith', lf.short_committer(rev))
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1069
1070
    def test_short_author(self):
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1071
        rev = revision.Revision('a-id')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1072
        rev.committer = 'John Doe <jdoe@example.com>'
3842.2.1 by Vincent Ladeuil
Cosmetic changes.
1073
        lf = log.LogFormatter(None)
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
1074
        self.assertEqual('John Doe', lf.short_author(rev))
1075
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
1076
        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.
1077
        rev.properties['author'] = 'John Smith'
1078
        self.assertEqual('John Smith', lf.short_author(rev))
1079
        rev.properties['author'] = 'jsmith@example.com'
1080
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
1081
        rev.properties['author'] = '<jsmith@example.com>'
1082
        self.assertEqual('jsmith@example.com', lf.short_author(rev))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1083
        rev.properties['author'] = 'John Smith jsmith@example.com'
1084
        self.assertEqual('John Smith', lf.short_author(rev))
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1085
1086
1087
class TestReverseByDepth(tests.TestCase):
1088
    """Test reverse_by_depth behavior.
1089
1090
    This is used to present revisions in forward (oldest first) order in a nice
1091
    layout.
1092
1093
    The tests use lighter revision description to ease reading.
1094
    """
1095
1096
    def assertReversed(self, forward, backward):
1097
        # Transform the descriptions to suit the API: tests use (revno, depth),
1098
        # while the API expects (revid, revno, depth)
1099
        def complete_revisions(l):
1100
            """Transform the description to suit the API.
1101
1102
            Tests use (revno, depth) whil the API expects (revid, revno, depth).
1103
            Since the revid is arbitrary, we just duplicate revno
1104
            """
1105
            return [ (r, r, d) for r, d in l]
1106
        forward = complete_revisions(forward)
1107
        backward= complete_revisions(backward)
1108
        self.assertEqual(forward, log.reverse_by_depth(backward))
1109
1110
1111
    def test_mainline_revisions(self):
1112
        self.assertReversed([( '1', 0), ('2', 0)],
1113
                            [('2', 0), ('1', 0)])
1114
1115
    def test_merged_revisions(self):
3842.2.3 by Vincent Ladeuil
Yet more cleanup and fix test_file_id_f3 bogus test.
1116
        self.assertReversed([('1', 0), ('2', 0), ('2.2', 1), ('2.1', 1),],
1117
                            [('2', 0), ('2.1', 1), ('2.2', 1), ('1', 0),])
3842.2.2 by Vincent Ladeuil
Reproduce bug #300055.
1118
    def test_shifted_merged_revisions(self):
1119
        """Test irregular layout.
1120
1121
        Requesting revisions touching a file can produce "holes" in the depths.
1122
        """
1123
        self.assertReversed([('1', 0), ('2', 0), ('1.1', 2), ('1.2', 2),],
1124
                            [('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.
1125
1126
    def test_merged_without_child_revisions(self):
1127
        """Test irregular layout.
1128
1129
        Revision ranges can produce "holes" in the depths.
1130
        """
1131
        # When a revision of higher depth doesn't follow one of lower depth, we
1132
        # assume a lower depth one is virtually there
1133
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1134
                            [('4', 4), ('3', 3), ('2', 2), ('1', 2),])
1135
        # So we get the same order after reversing below even if the original
1136
        # revisions are not in the same order.
1137
        self.assertReversed([('1', 2), ('2', 2), ('3', 3), ('4', 4)],
1138
                            [('3', 3), ('4', 4), ('2', 2), ('1', 2),])