~bzr-pqm/bzr/bzr.dev

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
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
20
from bzrlib import log
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
21
from bzrlib.tests import TestCase, TestCaseWithTransport
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
22
from bzrlib.log import (show_log,
23
                        get_view_revisions,
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.
24
                        LogRevision,
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
25
                        LogFormatter,
26
                        LongLogFormatter,
27
                        ShortLogFormatter,
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
28
                        LineLogFormatter)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
29
from bzrlib.branch import Branch
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
30
from bzrlib.errors import InvalidRevisionNumber
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
31
from bzrlib.revision import Revision
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
32
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
33
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
34
class LogCatcher(LogFormatter):
35
    """Pull log messages into list rather than displaying them.
36
37
    For ease of testing we save log messages here rather than actually
38
    formatting them, so that we can precisely check the result without
39
    being too dependent on the exact formatting.
40
41
    We should also test the LogFormatter.
42
    """
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.
43
2490.1.2 by John Arbash Meinel
Cleanup according to PEP8 and some other small whitespace fixes
44
    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.
45
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
46
    def __init__(self):
47
        super(LogCatcher, self).__init__(to_file=None)
48
        self.logs = []
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
49
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.
50
    def log_revision(self, revision):
51
        self.logs.append(revision)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
52
53
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
54
class TestShowLog(TestCaseWithTransport):
1102 by Martin Pool
- merge test refactoring from robertc
55
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
56
    def checkDelta(self, delta, **kw):
57
        """Check the filenames touched by a delta are as expected."""
58
        for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
59
            expected = kw.get(n, [])
60
            # strip out only the path components
61
            got = [x[0] for x in getattr(delta, n)]
62
            self.assertEquals(expected, got)
63
974.1.54 by aaron.bentley at utoronto
Fixed the revno bug in log
64
    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.
65
        wt = self.make_branch_and_tree('.')
66
        b = wt.branch
1092.3.4 by Robert Collins
update symlink branch to integration
67
68
        lf = LogCatcher()
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
69
        wt.commit('empty commit')
1092.3.4 by Robert Collins
update symlink branch to integration
70
        show_log(b, lf, verbose=True, start_revision=1, end_revision=1)
71
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
72
                          start_revision=2, end_revision=1) 
73
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
74
                          start_revision=1, end_revision=2) 
75
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
76
                          start_revision=0, end_revision=2) 
77
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
78
                          start_revision=1, end_revision=0) 
79
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
80
                          start_revision=-1, end_revision=1) 
81
        self.assertRaises(InvalidRevisionNumber, show_log, b, lf,
82
                          start_revision=1, end_revision=-1) 
83
1102 by Martin Pool
- merge test refactoring from robertc
84
    def test_simple_log(self):
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
85
        eq = self.assertEquals
86
        
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
87
        wt = self.make_branch_and_tree('.')
88
        b = wt.branch
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
89
90
        lf = LogCatcher()
91
        show_log(b, lf)
92
        # no entries yet
93
        eq(lf.logs, [])
94
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
95
        wt.commit('empty commit')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
96
        lf = LogCatcher()
97
        show_log(b, lf, verbose=True)
98
        eq(len(lf.logs), 1)
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
99
        eq(lf.logs[0].revno, '1')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
100
        eq(lf.logs[0].rev.message, 'empty commit')
101
        d = lf.logs[0].delta
102
        self.log('log delta: %r' % d)
103
        self.checkDelta(d)
104
105
        self.build_tree(['hello'])
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
106
        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.
107
        wt.commit('add one file',
108
                  committer=u'\u013d\xf3r\xe9m \xcdp\u0161\xfam '
109
                            u'<test@example.com>')
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
110
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
111
        lf = self.make_utf8_encoded_stringio()
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
112
        # log using regular thing
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
113
        show_log(b, LongLogFormatter(lf))
114
        lf.seek(0)
115
        for l in lf.readlines():
116
            self.log(l)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
117
118
        # get log as data structure
119
        lf = LogCatcher()
120
        show_log(b, lf, verbose=True)
121
        eq(len(lf.logs), 2)
122
        self.log('log entries:')
123
        for logentry in lf.logs:
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
124
            self.log('%4s %s' % (logentry.revno, logentry.rev.message))
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
125
        
126
        # first one is most recent
127
        logentry = lf.logs[0]
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
128
        eq(logentry.revno, '2')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
129
        eq(logentry.rev.message, 'add one file')
130
        d = logentry.delta
131
        self.log('log 2 delta: %r' % d)
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
132
        self.checkDelta(d, added=['hello'])
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
133
        
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
134
        # commit a log message with control characters
135
        msg = "All 8-bit chars: " +  ''.join([unichr(x) for x in range(256)])
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
136
        self.log("original commit message: %r", msg)
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
137
        wt.commit(msg)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
138
        lf = LogCatcher()
139
        show_log(b, lf, verbose=True)
140
        committed_msg = lf.logs[0].rev.message
141
        self.log("escaped commit message: %r", committed_msg)
142
        self.assert_(msg != committed_msg)
143
        self.assert_(len(committed_msg) > len(msg))
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
144
145
        # Check that log message with only XML-valid characters isn't
146
        # escaped.  As ElementTree apparently does some kind of
147
        # newline conversion, neither LF (\x0A) nor CR (\x0D) are
148
        # included in the test commit message, even though they are
149
        # valid XML 1.0 characters.
150
        msg = "\x09" + ''.join([unichr(x) for x in range(0x20, 256)])
151
        self.log("original commit message: %r", msg)
1534.4.36 by Robert Collins
Finish deprecating Branch.working_tree()
152
        wt.commit(msg)
1393.4.2 by Harald Meland
Cleanup + better test of commit-msg control character escape code.
153
        lf = LogCatcher()
154
        show_log(b, lf, verbose=True)
155
        committed_msg = lf.logs[0].rev.message
156
        self.log("escaped commit message: %r", committed_msg)
157
        self.assert_(msg == committed_msg)
1185.31.22 by John Arbash Meinel
[merge] bzr.dev
158
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
159
    def test_deltas_in_merge_revisions(self):
160
        """Check deltas created for both mainline and merge revisions"""
161
        eq = self.assertEquals
162
        wt = self.make_branch_and_tree('parent')
163
        self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
164
        wt.add('file1')
165
        wt.add('file2')
166
        wt.commit(message='add file1 and file2')
2581.1.6 by Martin Pool
fix up more run_bzr callers
167
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
168
        os.unlink('child/file1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
169
        file('child/file2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
170
        self.run_bzr(['commit', '-m', 'remove file1 and modify file2',
171
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
172
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
173
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
174
        wt.commit('merge child branch')
175
        os.chdir('..')
176
        b = wt.branch
177
        lf = LogCatcher()
178
        lf.supports_merge_revisions = True
179
        show_log(b, lf, verbose=True)
180
        eq(len(lf.logs),3)
181
        logentry = lf.logs[0]
182
        eq(logentry.revno, '2')
183
        eq(logentry.rev.message, 'merge child branch')
184
        d = logentry.delta
185
        self.checkDelta(d, removed=['file1'], modified=['file2'])
186
        logentry = lf.logs[1]
187
        eq(logentry.revno, '1.1.1')
188
        eq(logentry.rev.message, 'remove file1 and modify file2')
189
        d = logentry.delta
190
        self.checkDelta(d, removed=['file1'], modified=['file2'])
191
        logentry = lf.logs[2]
192
        eq(logentry.revno, '1')
193
        eq(logentry.rev.message, 'add file1 and file2')
194
        d = logentry.delta
195
        self.checkDelta(d, added=['file1', 'file2'])
196
197
198
def make_commits_with_trailing_newlines(wt):
199
    """Helper method for LogFormatter tests"""    
200
    b = wt.branch
201
    b.nick='test'
202
    open('a', 'wb').write('hello moto\n')
203
    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.
204
    wt.commit('simple log message', rev_id='a1',
205
              timestamp=1132586655.459960938, timezone=-6*3600,
206
              committer='Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
207
    open('b', 'wb').write('goodbye\n')
208
    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.
209
    wt.commit('multiline\nlog\nmessage\n', rev_id='a2',
210
              timestamp=1132586842.411175966, timezone=-6*3600,
211
              committer='Joe Foo <joe@foo.com>',
212
              author='Joe Bar <joe@bar.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
213
214
    open('c', 'wb').write('just another manic monday\n')
215
    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.
216
    wt.commit('single line with trailing newline\n', rev_id='a3',
217
              timestamp=1132587176.835228920, timezone=-6*3600,
218
              committer = 'Joe Foo <joe@foo.com>')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
219
    return b
220
221
222
class TestShortLogFormatter(TestCaseWithTransport):
223
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
224
    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.
225
        wt = self.make_branch_and_tree('.')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
226
        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.
227
        sio = self.make_utf8_encoded_stringio()
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
228
        lf = ShortLogFormatter(to_file=sio)
229
        show_log(b, lf)
230
        self.assertEquals(sio.getvalue(), """\
231
    3 Joe Foo\t2005-11-21
232
      single line with trailing newline
233
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.
234
    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.
235
      multiline
236
      log
237
      message
238
239
    1 Joe Foo\t2005-11-21
240
      simple log message
241
242
""")
243
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
244
245
class TestLongLogFormatter(TestCaseWithTransport):
246
247
    def normalize_log(self,log):
248
        """Replaces the variable lines of logs with fixed lines"""
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
249
        author = 'author: Dolor Sit <test@example.com>'
250
        committer = 'committer: Lorem Ipsum <test@example.com>'
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
251
        lines = log.splitlines(True)
252
        for idx,line in enumerate(lines):
253
            stripped_line = line.lstrip()
254
            indent = ' ' * (len(line) - len(stripped_line))
2671.5.4 by Lukáš Lalinsky
Replace the committer with the author in log, the committer is displayed only in the long format and only if it's different from the author.
255
            if stripped_line.startswith('author:'):
256
                lines[idx] = indent + author + '\n'
257
            elif stripped_line.startswith('committer:'):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
258
                lines[idx] = indent + committer + '\n'
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.
259
            elif stripped_line.startswith('timestamp:'):
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
260
                lines[idx] = indent + 'timestamp: Just now\n'
261
        return ''.join(lines)
262
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
263
    def test_verbose_log(self):
264
        """Verbose log includes changed files
265
        
266
        bug #4676
267
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
268
        wt = self.make_branch_and_tree('.')
269
        b = wt.branch
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
270
        self.build_tree(['a'])
1185.33.45 by Martin Pool
[merge] refactoring of branch vs working tree, etc (robertc)
271
        wt.add('a')
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
272
        # XXX: why does a longer nick show up?
273
        b.nick = 'test_verbose_log'
274
        wt.commit(message='add a', 
275
                  timestamp=1132711707, 
276
                  timezone=36000,
277
                  committer='Lorem Ipsum <test@example.com>')
278
        logfile = file('out.tmp', 'w+')
279
        formatter = LongLogFormatter(to_file=logfile)
280
        show_log(b, formatter, verbose=True)
281
        logfile.flush()
282
        logfile.seek(0)
283
        log_contents = logfile.read()
284
        self.assertEqualDiff(log_contents, '''\
285
------------------------------------------------------------
286
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
287
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)
288
branch nick: test_verbose_log
289
timestamp: Wed 2005-11-23 12:08:27 +1000
290
message:
291
  add a
292
added:
293
  a
294
''')
1185.85.4 by John Arbash Meinel
currently broken, trying to fix things up.
295
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
296
    def test_merges_are_indented_by_level(self):
297
        wt = self.make_branch_and_tree('parent')
298
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
299
        self.run_bzr('branch parent child')
300
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
301
        self.run_bzr('branch child smallerchild')
302
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
303
            'smallerchild'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
304
        os.chdir('child')
2581.1.6 by Martin Pool
fix up more run_bzr callers
305
        self.run_bzr('merge ../smallerchild')
306
        self.run_bzr(['commit', '-m', 'merge branch 2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
307
        os.chdir('../parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
308
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
309
        wt.commit('merge branch 1')
310
        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.
311
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
312
        lf = LongLogFormatter(to_file=sio)
313
        show_log(b, lf, verbose=True)
314
        log = self.normalize_log(sio.getvalue())
315
        self.assertEqualDiff("""\
316
------------------------------------------------------------
317
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
318
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
319
branch nick: parent
320
timestamp: Just now
321
message:
322
  merge branch 1
323
    ------------------------------------------------------------
324
    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.
325
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
326
    branch nick: child
327
    timestamp: Just now
328
    message:
329
      merge branch 2
330
        ------------------------------------------------------------
331
        revno: 1.1.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.
332
        committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
333
        branch nick: smallerchild
334
        timestamp: Just now
335
        message:
336
          branch 2
337
    ------------------------------------------------------------
338
    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.
339
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
340
    branch nick: child
341
    timestamp: Just now
342
    message:
343
      branch 1
344
------------------------------------------------------------
345
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
346
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
347
branch nick: parent
348
timestamp: Just now
349
message:
350
  first post
351
""", log)
352
353
    def test_verbose_merge_revisions_contain_deltas(self):
354
        wt = self.make_branch_and_tree('parent')
355
        self.build_tree(['parent/f1', 'parent/f2'])
356
        wt.add(['f1','f2'])
357
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
358
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
359
        os.unlink('child/f1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
360
        file('child/f2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
361
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
362
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
363
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
364
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
365
        wt.commit('merge branch 1')
366
        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.
367
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
368
        lf = LongLogFormatter(to_file=sio)
369
        show_log(b, lf, verbose=True)
370
        log = self.normalize_log(sio.getvalue())
371
        self.assertEqualDiff("""\
372
------------------------------------------------------------
373
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
374
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
375
branch nick: parent
376
timestamp: Just now
377
message:
378
  merge branch 1
379
removed:
380
  f1
381
modified:
382
  f2
383
    ------------------------------------------------------------
384
    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.
385
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
386
    branch nick: child
387
    timestamp: Just now
388
    message:
389
      removed f1 and modified f2
390
    removed:
391
      f1
392
    modified:
393
      f2
394
------------------------------------------------------------
395
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
396
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
397
branch nick: parent
398
timestamp: Just now
399
message:
400
  first post
401
added:
402
  f1
403
  f2
404
""", log)
405
406
    def test_trailing_newlines(self):
407
        wt = self.make_branch_and_tree('.')
408
        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.
409
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
410
        lf = LongLogFormatter(to_file=sio)
411
        show_log(b, lf)
412
        self.assertEqualDiff(sio.getvalue(), """\
413
------------------------------------------------------------
414
revno: 3
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
415
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
416
branch nick: test
417
timestamp: Mon 2005-11-21 09:32:56 -0600
418
message:
419
  single line with trailing newline
420
------------------------------------------------------------
421
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.
422
author: Joe Bar <joe@bar.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
423
committer: Joe Foo <joe@foo.com>
424
branch nick: test
425
timestamp: Mon 2005-11-21 09:27:22 -0600
426
message:
427
  multiline
428
  log
429
  message
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: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
433
branch nick: test
434
timestamp: Mon 2005-11-21 09:24:15 -0600
435
message:
436
  simple log message
437
""")
438
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
439
    def test_author_in_log(self):
440
        """Log includes the author name if it's set in
441
        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.
442
        """
443
        wt = self.make_branch_and_tree('.')
444
        b = wt.branch
445
        self.build_tree(['a'])
446
        wt.add('a')
447
        b.nick = 'test_author_log'
448
        wt.commit(message='add a',
449
                  timestamp=1132711707,
450
                  timezone=36000,
451
                  committer='Lorem Ipsum <test@example.com>',
2671.2.5 by Lukáš Lalinský
Fixes for comments from the mailing list.
452
                  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.
453
        sio = StringIO()
454
        formatter = LongLogFormatter(to_file=sio)
455
        show_log(b, formatter)
456
        self.assertEqualDiff(sio.getvalue(), '''\
457
------------------------------------------------------------
458
revno: 1
459
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.
460
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.
461
branch nick: test_author_log
462
timestamp: Wed 2005-11-23 12:08:27 +1000
463
message:
464
  add a
465
''')
466
467
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
468
469
class TestLineLogFormatter(TestCaseWithTransport):
470
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
471
    def test_line_log(self):
472
        """Line log should show revno
473
        
474
        bug #5162
475
        """
476
        wt = self.make_branch_and_tree('.')
477
        b = wt.branch
478
        self.build_tree(['a'])
479
        wt.add('a')
480
        b.nick = 'test-line-log'
481
        wt.commit(message='add a', 
482
                  timestamp=1132711707, 
483
                  timezone=36000,
484
                  committer='Line-Log-Formatter Tester <test@line.log>')
485
        logfile = file('out.tmp', 'w+')
486
        formatter = LineLogFormatter(to_file=logfile)
487
        show_log(b, formatter)
488
        logfile.flush()
489
        logfile.seek(0)
490
        log_contents = logfile.read()
491
        self.assertEqualDiff(log_contents, '1: Line-Log-Formatte... 2005-11-23 add a\n')
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
492
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
493
    def test_short_log_with_merges(self):
494
        wt = self.make_branch_and_memory_tree('.')
495
        wt.lock_write()
496
        try:
497
            wt.add('')
498
            wt.commit('rev-1', rev_id='rev-1',
499
                      timestamp=1132586655, timezone=36000,
500
                      committer='Joe Foo <joe@foo.com>')
501
            wt.commit('rev-merged', rev_id='rev-2a',
502
                      timestamp=1132586700, timezone=36000,
503
                      committer='Joe Foo <joe@foo.com>')
504
            wt.set_parent_ids(['rev-1', 'rev-2a'])
505
            wt.branch.set_last_revision_info(1, 'rev-1')
506
            wt.commit('rev-2', rev_id='rev-2b',
507
                      timestamp=1132586800, timezone=36000,
508
                      committer='Joe Foo <joe@foo.com>')
2717.1.1 by Lukáš Lalinsky
Use UTF-8 encoded StringIO for log tests to avoid failures on non-ASCII committer names.
509
            logfile = self.make_utf8_encoded_stringio()
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
510
            formatter = ShortLogFormatter(to_file=logfile)
511
            show_log(wt.branch, formatter)
512
            logfile.flush()
513
            self.assertEqualDiff("""\
2483.2.2 by John Arbash Meinel
Add [merge] after the timestamp for revisions with merges.
514
    2 Joe Foo\t2005-11-22 [merge]
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
515
      rev-2
516
517
    1 Joe Foo\t2005-11-22
518
      rev-1
519
520
""", logfile.getvalue())
521
        finally:
522
            wt.unlock()
523
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
524
    def test_trailing_newlines(self):
525
        wt = self.make_branch_and_tree('.')
526
        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.
527
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
528
        lf = LineLogFormatter(to_file=sio)
529
        show_log(b, lf)
530
        self.assertEqualDiff(sio.getvalue(), """\
531
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.
532
2: Joe Bar 2005-11-21 multiline
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
533
1: Joe Foo 2005-11-21 simple log message
534
""")
535
536
537
class TestGetViewRevisions(TestCaseWithTransport):
538
1756.2.22 by Aaron Bentley
Apply review comments
539
    def make_tree_with_commits(self):
540
        """Create a tree with well-known revision ids"""
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
541
        wt = self.make_branch_and_tree('tree1')
542
        wt.commit('commit one', rev_id='1')
543
        wt.commit('commit two', rev_id='2')
544
        wt.commit('commit three', rev_id='3')
545
        mainline_revs = [None, '1', '2', '3']
1756.2.22 by Aaron Bentley
Apply review comments
546
        rev_nos = {'1': 1, '2': 2, '3': 3}
547
        return mainline_revs, rev_nos, wt
548
549
    def make_tree_with_merges(self):
550
        """Create a tree with well-known revision ids and a merge"""
551
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
552
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
553
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
554
        wt.merge_from_branch(tree2.branch)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
555
        wt.commit('four-b', rev_id='4b')
556
        mainline_revs.append('4b')
1756.2.22 by Aaron Bentley
Apply review comments
557
        rev_nos['4b'] = 4
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
558
        # 4a: 3.1.1
1756.2.22 by Aaron Bentley
Apply review comments
559
        return mainline_revs, rev_nos, wt
560
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
561
    def make_tree_with_many_merges(self):
562
        """Create a tree with well-known revision ids"""
563
        wt = self.make_branch_and_tree('tree1')
564
        wt.commit('commit one', rev_id='1')
565
        wt.commit('commit two', rev_id='2')
566
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
567
        tree3.commit('commit three a', rev_id='3a')
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
568
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
569
        tree2.merge_from_branch(tree3.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
570
        tree2.commit('commit three b', rev_id='3b')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
571
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
572
        wt.commit('commit three c', rev_id='3c')
573
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
574
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
575
        wt.commit('four-b', rev_id='4b')
576
        mainline_revs = [None, '1', '2', '3c', '4b']
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
577
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
578
        full_rev_nos_for_reference = {
579
            '1': '1',
580
            '2': '2',
581
            '3a': '2.2.1', #first commit tree 3
582
            '3b': '2.1.1', # first commit tree 2
583
            '3c': '3', #merges 3b to main
584
            '4a': '2.1.2', # second commit tree 2
585
            '4b': '4', # merges 4a to main
586
            }
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
587
        return mainline_revs, rev_nos, wt
588
1756.2.22 by Aaron Bentley
Apply review comments
589
    def test_get_view_revisions_forward(self):
590
        """Test the get_view_revisions method"""
591
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
592
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
593
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
594
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
595
            revisions)
1756.2.22 by Aaron Bentley
Apply review comments
596
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
597
                                             'forward', include_merges=False))
598
        self.assertEqual(revisions, revisions2)
599
600
    def test_get_view_revisions_reverse(self):
601
        """Test the get_view_revisions with reverse"""
602
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
603
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
604
                                            'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
605
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
606
            revisions)
1756.2.22 by Aaron Bentley
Apply review comments
607
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
608
                                             'reverse', include_merges=False))
609
        self.assertEqual(revisions, revisions2)
610
611
    def test_get_view_revisions_merge(self):
612
        """Test get_view_revisions when there are merges"""
613
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
614
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
615
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
616
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
617
            ('4b', '4', 0), ('4a', '3.1.1', 1)],
618
            revisions)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
619
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
1756.2.22 by Aaron Bentley
Apply review comments
620
                                             'forward', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
621
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
622
            ('4b', '4', 0)],
623
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
624
625
    def test_get_view_revisions_merge_reverse(self):
626
        """Test get_view_revisions in reverse when there are merges"""
627
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
628
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
629
                                            'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
630
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
631
            ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
632
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
633
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
634
                                             'reverse', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
635
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
636
            ('1', '1', 0)],
637
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
638
639
    def test_get_view_revisions_merge2(self):
640
        """Test get_view_revisions when there are merges"""
641
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
642
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
643
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
644
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
645
            ('3a', '2.2.1', 1), ('3b', '2.1.1', 1), ('4b', '4', 0),
646
            ('4a', '2.1.2', 1)]
647
        self.assertEqual(expected, revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
648
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
649
                                             'forward', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
650
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
651
            ('4b', '4', 0)],
652
            revisions)
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
653
654
655
class TestGetRevisionsTouchingFileID(TestCaseWithTransport):
656
657
    def create_tree_with_single_merge(self):
658
        """Create a branch with a moderate layout.
659
660
        The revision graph looks like:
661
662
           A
663
           |\
664
           B C
665
           |/
666
           D
667
668
        In this graph, A introduced files f1 and f2 and f3.
669
        B modifies f1 and f3, and C modifies f2 and f3.
670
        D merges the changes from B and C and resolves the conflict for f3.
671
        """
672
        # TODO: jam 20070218 This seems like it could really be done
673
        #       with make_branch_and_memory_tree() if we could just
674
        #       create the content of those files.
675
        # TODO: jam 20070218 Another alternative is that we would really
676
        #       like to only create this tree 1 time for all tests that
677
        #       use it. Since 'log' only uses the tree in a readonly
678
        #       fashion, it seems a shame to regenerate an identical
679
        #       tree for each test.
680
        tree = self.make_branch_and_tree('tree')
681
        tree.lock_write()
682
        self.addCleanup(tree.unlock)
683
684
        self.build_tree_contents([('tree/f1', 'A\n'),
685
                                  ('tree/f2', 'A\n'),
686
                                  ('tree/f3', 'A\n'),
687
                                 ])
688
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
689
        tree.commit('A', rev_id='A')
690
691
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
692
                                  ('tree/f3', 'A\nC\n'),
693
                                 ])
694
        tree.commit('C', rev_id='C')
695
        # Revert back to A to build the other history.
696
        tree.set_last_revision('A')
697
        tree.branch.set_last_revision_info(1, 'A')
698
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
699
                                  ('tree/f2', 'A\n'),
700
                                  ('tree/f3', 'A\nB\n'),
701
                                 ])
702
        tree.commit('B', rev_id='B')
703
        tree.set_parent_ids(['B', 'C'])
704
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
705
                                  ('tree/f2', 'A\nC\n'),
706
                                  ('tree/f3', 'A\nB\nC\n'),
707
                                 ])
708
        tree.commit('D', rev_id='D')
709
710
        # Switch to a read lock for this tree.
711
        # We still have addCleanup(unlock)
712
        tree.unlock()
713
        tree.lock_read()
714
        return tree
715
716
    def test_tree_with_single_merge(self):
717
        """Make sure the tree layout is correct."""
718
        tree = self.create_tree_with_single_merge()
719
        rev_A_tree = tree.branch.repository.revision_tree('A')
720
        rev_B_tree = tree.branch.repository.revision_tree('B')
721
722
        f1_changed = (u'f1', 'f1-id', 'file', True, False)
723
        f2_changed = (u'f2', 'f2-id', 'file', True, False)
724
        f3_changed = (u'f3', 'f3-id', 'file', True, False)
725
726
        delta = rev_B_tree.changes_from(rev_A_tree)
727
        self.assertEqual([f1_changed, f3_changed], delta.modified)
728
        self.assertEqual([], delta.renamed)
729
        self.assertEqual([], delta.added)
730
        self.assertEqual([], delta.removed)
731
732
        rev_C_tree = tree.branch.repository.revision_tree('C')
733
        delta = rev_C_tree.changes_from(rev_A_tree)
734
        self.assertEqual([f2_changed, f3_changed], delta.modified)
735
        self.assertEqual([], delta.renamed)
736
        self.assertEqual([], delta.added)
737
        self.assertEqual([], delta.removed)
738
739
        rev_D_tree = tree.branch.repository.revision_tree('D')
740
        delta = rev_D_tree.changes_from(rev_B_tree)
741
        self.assertEqual([f2_changed, f3_changed], delta.modified)
742
        self.assertEqual([], delta.renamed)
743
        self.assertEqual([], delta.added)
744
        self.assertEqual([], delta.removed)
745
746
        delta = rev_D_tree.changes_from(rev_C_tree)
747
        self.assertEqual([f1_changed, f3_changed], delta.modified)
748
        self.assertEqual([], delta.renamed)
749
        self.assertEqual([], delta.added)
750
        self.assertEqual([], delta.removed)
751
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
752
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
753
        """Make sure _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
754
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
755
        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
756
        sure they are correct.
757
        """
758
        # The api for _get_revisions_touching_file_id is a little crazy,
759
        # So we do the setup here.
760
        mainline = tree.branch.revision_history()
761
        mainline.insert(0, None)
762
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
763
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
764
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
765
        actual_revs = log._filter_revisions_touching_file_id(
766
                            tree.branch, 
767
                            file_id,
768
                            mainline,
769
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
770
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
771
772
    def test_file_id_f1(self):
773
        tree = self.create_tree_with_single_merge()
774
        # f1 should be marked as modified by revisions A and B
775
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
776
777
    def test_file_id_f2(self):
778
        tree = self.create_tree_with_single_merge()
779
        # f2 should be marked as modified by revisions A, C, and D
780
        # because D merged the changes from C.
781
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
782
783
    def test_file_id_f3(self):
784
        tree = self.create_tree_with_single_merge()
785
        # f3 should be marked as modified by revisions A, B, C, and D
786
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
787
788
789
class TestShowChangedRevisions(TestCaseWithTransport):
790
791
    def test_show_changed_revisions_verbose(self):
792
        tree = self.make_branch_and_tree('tree_a')
793
        self.build_tree(['tree_a/foo'])
794
        tree.add('foo')
795
        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.
796
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
797
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
798
        self.assertContainsRe(s.getvalue(), 'bar')
799
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
800
801
802
class TestLogFormatter(TestCase):
803
804
    def test_short_committer(self):
805
        rev = Revision('a-id')
806
        rev.committer = 'John Doe <jdoe@example.com>'
807
        lf = LogFormatter(None)
808
        self.assertEqual('John Doe', lf.short_committer(rev))
809
810
    def test_short_author(self):
811
        rev = Revision('a-id')
812
        rev.committer = 'John Doe <jdoe@example.com>'
813
        lf = LogFormatter(None)
814
        self.assertEqual('John Doe', lf.short_author(rev))
815
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
816
        self.assertEqual('John Smith', lf.short_author(rev))