~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
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
222
def normalize_log(log):
223
    """Replaces the variable lines of logs with fixed lines"""
224
    author = 'author: Dolor Sit <test@example.com>'
225
    committer = 'committer: Lorem Ipsum <test@example.com>'
226
    lines = log.splitlines(True)
227
    for idx,line in enumerate(lines):
228
        stripped_line = line.lstrip()
229
        indent = ' ' * (len(line) - len(stripped_line))
230
        if stripped_line.startswith('author:'):
231
            lines[idx] = indent + author + '\n'
232
        elif stripped_line.startswith('committer:'):
233
            lines[idx] = indent + committer + '\n'
234
        elif stripped_line.startswith('timestamp:'):
235
            lines[idx] = indent + 'timestamp: Just now\n'
236
    return ''.join(lines)
237
238
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
239
class TestShortLogFormatter(TestCaseWithTransport):
240
1185.31.21 by John Arbash Meinel
Added test for log formatting, found bug when redirecting short logs to a file instead of stdout.
241
    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.
242
        wt = self.make_branch_and_tree('.')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
243
        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.
244
        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.
245
        lf = ShortLogFormatter(to_file=sio)
246
        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.
247
        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.
248
    3 Joe Foo\t2005-11-21
249
      single line with trailing newline
250
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.
251
    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.
252
      multiline
253
      log
254
      message
255
256
    1 Joe Foo\t2005-11-21
257
      simple log message
258
259
""")
260
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
261
262
class TestLongLogFormatter(TestCaseWithTransport):
263
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
264
    def test_verbose_log(self):
265
        """Verbose log includes changed files
266
        
267
        bug #4676
268
        """
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
269
        wt = self.make_branch_and_tree('.')
270
        b = wt.branch
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
271
        self.build_tree(['a'])
1185.33.45 by Martin Pool
[merge] refactoring of branch vs working tree, etc (robertc)
272
        wt.add('a')
1185.33.41 by Martin Pool
Fix regression of 'bzr log -v' - it wasn't showing changed files at all. (#4676)
273
        # XXX: why does a longer nick show up?
274
        b.nick = 'test_verbose_log'
275
        wt.commit(message='add a', 
276
                  timestamp=1132711707, 
277
                  timezone=36000,
278
                  committer='Lorem Ipsum <test@example.com>')
279
        logfile = file('out.tmp', 'w+')
280
        formatter = LongLogFormatter(to_file=logfile)
281
        show_log(b, formatter, verbose=True)
282
        logfile.flush()
283
        logfile.seek(0)
284
        log_contents = logfile.read()
285
        self.assertEqualDiff(log_contents, '''\
286
------------------------------------------------------------
287
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
288
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)
289
branch nick: test_verbose_log
290
timestamp: Wed 2005-11-23 12:08:27 +1000
291
message:
292
  add a
293
added:
294
  a
295
''')
1185.85.4 by John Arbash Meinel
currently broken, trying to fix things up.
296
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
297
    def test_merges_are_indented_by_level(self):
298
        wt = self.make_branch_and_tree('parent')
299
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
300
        self.run_bzr('branch parent child')
301
        self.run_bzr(['commit', '-m', 'branch 1', '--unchanged', 'child'])
302
        self.run_bzr('branch child smallerchild')
303
        self.run_bzr(['commit', '-m', 'branch 2', '--unchanged',
304
            'smallerchild'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
305
        os.chdir('child')
2581.1.6 by Martin Pool
fix up more run_bzr callers
306
        self.run_bzr('merge ../smallerchild')
307
        self.run_bzr(['commit', '-m', 'merge branch 2'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
308
        os.chdir('../parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
309
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
310
        wt.commit('merge branch 1')
311
        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.
312
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
313
        lf = LongLogFormatter(to_file=sio)
314
        show_log(b, lf, verbose=True)
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
315
        log = normalize_log(sio.getvalue())
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.
316
        self.assertEqualDiff(log, """\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
317
------------------------------------------------------------
318
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
319
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
320
branch nick: parent
321
timestamp: Just now
322
message:
323
  merge branch 1
324
    ------------------------------------------------------------
325
    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.
326
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
327
    branch nick: child
328
    timestamp: Just now
329
    message:
330
      merge branch 2
331
        ------------------------------------------------------------
332
        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.
333
        committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
334
        branch nick: smallerchild
335
        timestamp: Just now
336
        message:
337
          branch 2
338
    ------------------------------------------------------------
339
    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.
340
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
341
    branch nick: child
342
    timestamp: Just now
343
    message:
344
      branch 1
345
------------------------------------------------------------
346
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
347
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
348
branch nick: parent
349
timestamp: Just now
350
message:
351
  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.
352
""")
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
353
354
    def test_verbose_merge_revisions_contain_deltas(self):
355
        wt = self.make_branch_and_tree('parent')
356
        self.build_tree(['parent/f1', 'parent/f2'])
357
        wt.add(['f1','f2'])
358
        wt.commit('first post')
2581.1.6 by Martin Pool
fix up more run_bzr callers
359
        self.run_bzr('branch parent child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
360
        os.unlink('child/f1')
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
361
        file('child/f2', 'wb').write('hello\n')
2581.1.6 by Martin Pool
fix up more run_bzr callers
362
        self.run_bzr(['commit', '-m', 'removed f1 and modified f2',
363
            'child'])
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
364
        os.chdir('parent')
2581.1.6 by Martin Pool
fix up more run_bzr callers
365
        self.run_bzr('merge ../child')
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
366
        wt.commit('merge branch 1')
367
        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.
368
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
369
        lf = LongLogFormatter(to_file=sio)
370
        show_log(b, lf, verbose=True)
2978.6.1 by Kent Gibson
Use normalize_log to more accurately test blackbox log output.
371
        log = normalize_log(sio.getvalue())
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.
372
        self.assertEqualDiff(log, """\
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
373
------------------------------------------------------------
374
revno: 2
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
375
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
376
branch nick: parent
377
timestamp: Just now
378
message:
379
  merge branch 1
380
removed:
381
  f1
382
modified:
383
  f2
384
    ------------------------------------------------------------
385
    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.
386
    committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
387
    branch nick: child
388
    timestamp: Just now
389
    message:
390
      removed f1 and modified f2
391
    removed:
392
      f1
393
    modified:
394
      f2
395
------------------------------------------------------------
396
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
397
committer: Lorem Ipsum <test@example.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
398
branch nick: parent
399
timestamp: Just now
400
message:
401
  first post
402
added:
403
  f1
404
  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.
405
""")
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
406
407
    def test_trailing_newlines(self):
408
        wt = self.make_branch_and_tree('.')
409
        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.
410
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
411
        lf = LongLogFormatter(to_file=sio)
412
        show_log(b, lf)
413
        self.assertEqualDiff(sio.getvalue(), """\
414
------------------------------------------------------------
415
revno: 3
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
416
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
417
branch nick: test
418
timestamp: Mon 2005-11-21 09:32:56 -0600
419
message:
420
  single line with trailing newline
421
------------------------------------------------------------
422
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.
423
author: Joe Bar <joe@bar.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
424
committer: Joe Foo <joe@foo.com>
425
branch nick: test
426
timestamp: Mon 2005-11-21 09:27:22 -0600
427
message:
428
  multiline
429
  log
430
  message
431
------------------------------------------------------------
432
revno: 1
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
433
committer: Joe Foo <joe@foo.com>
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
434
branch nick: test
435
timestamp: Mon 2005-11-21 09:24:15 -0600
436
message:
437
  simple log message
438
""")
439
2671.5.7 by Lukáš Lalinsky
Rename get_author to get_apparent_author, revert the long log back to displaying the committer.
440
    def test_author_in_log(self):
441
        """Log includes the author name if it's set in
442
        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.
443
        """
444
        wt = self.make_branch_and_tree('.')
445
        b = wt.branch
446
        self.build_tree(['a'])
447
        wt.add('a')
448
        b.nick = 'test_author_log'
449
        wt.commit(message='add a',
450
                  timestamp=1132711707,
451
                  timezone=36000,
452
                  committer='Lorem Ipsum <test@example.com>',
2671.2.5 by Lukáš Lalinský
Fixes for comments from the mailing list.
453
                  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.
454
        sio = StringIO()
455
        formatter = LongLogFormatter(to_file=sio)
456
        show_log(b, formatter)
457
        self.assertEqualDiff(sio.getvalue(), '''\
458
------------------------------------------------------------
459
revno: 1
460
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.
461
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.
462
branch nick: test_author_log
463
timestamp: Wed 2005-11-23 12:08:27 +1000
464
message:
465
  add a
466
''')
467
468
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
469
470
class TestLineLogFormatter(TestCaseWithTransport):
471
1704.2.20 by Martin Pool
log --line shows revision numbers (Alexander)
472
    def test_line_log(self):
473
        """Line log should show revno
474
        
475
        bug #5162
476
        """
477
        wt = self.make_branch_and_tree('.')
478
        b = wt.branch
479
        self.build_tree(['a'])
480
        wt.add('a')
481
        b.nick = 'test-line-log'
482
        wt.commit(message='add a', 
483
                  timestamp=1132711707, 
484
                  timezone=36000,
485
                  committer='Line-Log-Formatter Tester <test@line.log>')
486
        logfile = file('out.tmp', 'w+')
487
        formatter = LineLogFormatter(to_file=logfile)
488
        show_log(b, formatter)
489
        logfile.flush()
490
        logfile.seek(0)
491
        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.
492
        self.assertEqualDiff(log_contents,
493
            '1: Line-Log-Formatte... 2005-11-23 add a\n')
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
494
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
495
    def test_short_log_with_merges(self):
496
        wt = self.make_branch_and_memory_tree('.')
497
        wt.lock_write()
498
        try:
499
            wt.add('')
500
            wt.commit('rev-1', rev_id='rev-1',
501
                      timestamp=1132586655, timezone=36000,
502
                      committer='Joe Foo <joe@foo.com>')
503
            wt.commit('rev-merged', rev_id='rev-2a',
504
                      timestamp=1132586700, timezone=36000,
505
                      committer='Joe Foo <joe@foo.com>')
506
            wt.set_parent_ids(['rev-1', 'rev-2a'])
507
            wt.branch.set_last_revision_info(1, 'rev-1')
508
            wt.commit('rev-2', rev_id='rev-2b',
509
                      timestamp=1132586800, timezone=36000,
510
                      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.
511
            logfile = self.make_utf8_encoded_stringio()
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
512
            formatter = ShortLogFormatter(to_file=logfile)
513
            show_log(wt.branch, formatter)
514
            logfile.flush()
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.
515
            self.assertEqualDiff(logfile.getvalue(), """\
2483.2.2 by John Arbash Meinel
Add [merge] after the timestamp for revisions with merges.
516
    2 Joe Foo\t2005-11-22 [merge]
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
517
      rev-2
518
519
    1 Joe Foo\t2005-11-22
520
      rev-1
521
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.
522
""")
2483.2.1 by John Arbash Meinel
Add a test with a merged revision
523
        finally:
524
            wt.unlock()
525
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
526
    def test_trailing_newlines(self):
527
        wt = self.make_branch_and_tree('.')
528
        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.
529
        sio = self.make_utf8_encoded_stringio()
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
530
        lf = LineLogFormatter(to_file=sio)
531
        show_log(b, lf)
532
        self.assertEqualDiff(sio.getvalue(), """\
533
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.
534
2: Joe Bar 2005-11-21 multiline
2466.11.2 by Kent Gibson
Add tests for deltas in merge revisions
535
1: Joe Foo 2005-11-21 simple log message
536
""")
537
538
539
class TestGetViewRevisions(TestCaseWithTransport):
540
1756.2.22 by Aaron Bentley
Apply review comments
541
    def make_tree_with_commits(self):
542
        """Create a tree with well-known revision ids"""
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
543
        wt = self.make_branch_and_tree('tree1')
544
        wt.commit('commit one', rev_id='1')
545
        wt.commit('commit two', rev_id='2')
546
        wt.commit('commit three', rev_id='3')
547
        mainline_revs = [None, '1', '2', '3']
1756.2.22 by Aaron Bentley
Apply review comments
548
        rev_nos = {'1': 1, '2': 2, '3': 3}
549
        return mainline_revs, rev_nos, wt
550
551
    def make_tree_with_merges(self):
552
        """Create a tree with well-known revision ids and a merge"""
553
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
554
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
555
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
556
        wt.merge_from_branch(tree2.branch)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
557
        wt.commit('four-b', rev_id='4b')
558
        mainline_revs.append('4b')
1756.2.22 by Aaron Bentley
Apply review comments
559
        rev_nos['4b'] = 4
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
560
        # 4a: 3.1.1
1756.2.22 by Aaron Bentley
Apply review comments
561
        return mainline_revs, rev_nos, wt
562
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
563
    def make_tree_with_many_merges(self):
564
        """Create a tree with well-known revision ids"""
565
        wt = self.make_branch_and_tree('tree1')
566
        wt.commit('commit one', rev_id='1')
567
        wt.commit('commit two', rev_id='2')
568
        tree3 = wt.bzrdir.sprout('tree3').open_workingtree()
569
        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,
570
        tree2 = wt.bzrdir.sprout('tree2').open_workingtree()
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
571
        tree2.merge_from_branch(tree3.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
572
        tree2.commit('commit three b', rev_id='3b')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
573
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
574
        wt.commit('commit three c', rev_id='3c')
575
        tree2.commit('four-a', rev_id='4a')
1979.2.1 by Robert Collins
(robertc) adds a convenience method "merge_from_branch" to WorkingTree.
576
        wt.merge_from_branch(tree2.branch)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
577
        wt.commit('four-b', rev_id='4b')
578
        mainline_revs = [None, '1', '2', '3c', '4b']
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
579
        rev_nos = {'1':1, '2':2, '3c': 3, '4b':4}
580
        full_rev_nos_for_reference = {
581
            '1': '1',
582
            '2': '2',
583
            '3a': '2.2.1', #first commit tree 3
584
            '3b': '2.1.1', # first commit tree 2
585
            '3c': '3', #merges 3b to main
586
            '4a': '2.1.2', # second commit tree 2
587
            '4b': '4', # merges 4a to main
588
            }
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
589
        return mainline_revs, rev_nos, wt
590
1756.2.22 by Aaron Bentley
Apply review comments
591
    def test_get_view_revisions_forward(self):
592
        """Test the get_view_revisions method"""
593
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
594
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
595
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
596
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0)],
597
            revisions)
1756.2.22 by Aaron Bentley
Apply review comments
598
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
599
                                             'forward', include_merges=False))
600
        self.assertEqual(revisions, revisions2)
601
602
    def test_get_view_revisions_reverse(self):
603
        """Test the get_view_revisions with reverse"""
604
        mainline_revs, rev_nos, wt = self.make_tree_with_commits()
605
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
606
                                            'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
607
        self.assertEqual([('3', '3', 0), ('2', '2', 0), ('1', '1', 0), ],
608
            revisions)
1756.2.22 by Aaron Bentley
Apply review comments
609
        revisions2 = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
610
                                             'reverse', include_merges=False))
611
        self.assertEqual(revisions, revisions2)
612
613
    def test_get_view_revisions_merge(self):
614
        """Test get_view_revisions when there are merges"""
615
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
616
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
617
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
618
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
619
            ('4b', '4', 0), ('4a', '3.1.1', 1)],
620
            revisions)
1756.2.20 by Aaron Bentley
Optimize log formats that don't show merges
621
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
1756.2.22 by Aaron Bentley
Apply review comments
622
                                             'forward', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
623
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3', '3', 0),
624
            ('4b', '4', 0)],
625
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
626
627
    def test_get_view_revisions_merge_reverse(self):
628
        """Test get_view_revisions in reverse when there are merges"""
629
        mainline_revs, rev_nos, wt = self.make_tree_with_merges()
630
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
631
                                            'reverse'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
632
        self.assertEqual([('4b', '4', 0), ('4a', '3.1.1', 1),
633
            ('3', '3', 0), ('2', '2', 0), ('1', '1', 0)],
634
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
635
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
636
                                             'reverse', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
637
        self.assertEqual([('4b', '4', 0), ('3', '3', 0), ('2', '2', 0),
638
            ('1', '1', 0)],
639
            revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
640
641
    def test_get_view_revisions_merge2(self):
642
        """Test get_view_revisions when there are merges"""
643
        mainline_revs, rev_nos, wt = self.make_tree_with_many_merges()
644
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
645
                                            'forward'))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
646
        expected = [('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
647
            ('3a', '2.2.1', 1), ('3b', '2.1.1', 1), ('4b', '4', 0),
648
            ('4a', '2.1.2', 1)]
649
        self.assertEqual(expected, revisions)
1756.2.24 by Aaron Bentley
Forward sorting shows merges under mainline revision
650
        revisions = list(get_view_revisions(mainline_revs, rev_nos, wt.branch,
651
                                             'forward', include_merges=False))
1988.4.2 by Robert Collins
``bzr log`` Now shows dotted-decimal revision numbers for all revisions,
652
        self.assertEqual([('1', '1', 0), ('2', '2', 0), ('3c', '3', 0),
653
            ('4b', '4', 0)],
654
            revisions)
2359.1.6 by John Arbash Meinel
Create a helper tree which has a semi-interesting history.
655
656
657
class TestGetRevisionsTouchingFileID(TestCaseWithTransport):
658
659
    def create_tree_with_single_merge(self):
660
        """Create a branch with a moderate layout.
661
662
        The revision graph looks like:
663
664
           A
665
           |\
666
           B C
667
           |/
668
           D
669
670
        In this graph, A introduced files f1 and f2 and f3.
671
        B modifies f1 and f3, and C modifies f2 and f3.
672
        D merges the changes from B and C and resolves the conflict for f3.
673
        """
674
        # TODO: jam 20070218 This seems like it could really be done
675
        #       with make_branch_and_memory_tree() if we could just
676
        #       create the content of those files.
677
        # TODO: jam 20070218 Another alternative is that we would really
678
        #       like to only create this tree 1 time for all tests that
679
        #       use it. Since 'log' only uses the tree in a readonly
680
        #       fashion, it seems a shame to regenerate an identical
681
        #       tree for each test.
682
        tree = self.make_branch_and_tree('tree')
683
        tree.lock_write()
684
        self.addCleanup(tree.unlock)
685
686
        self.build_tree_contents([('tree/f1', 'A\n'),
687
                                  ('tree/f2', 'A\n'),
688
                                  ('tree/f3', 'A\n'),
689
                                 ])
690
        tree.add(['f1', 'f2', 'f3'], ['f1-id', 'f2-id', 'f3-id'])
691
        tree.commit('A', rev_id='A')
692
693
        self.build_tree_contents([('tree/f2', 'A\nC\n'),
694
                                  ('tree/f3', 'A\nC\n'),
695
                                 ])
696
        tree.commit('C', rev_id='C')
697
        # Revert back to A to build the other history.
698
        tree.set_last_revision('A')
699
        tree.branch.set_last_revision_info(1, 'A')
700
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
701
                                  ('tree/f2', 'A\n'),
702
                                  ('tree/f3', 'A\nB\n'),
703
                                 ])
704
        tree.commit('B', rev_id='B')
705
        tree.set_parent_ids(['B', 'C'])
706
        self.build_tree_contents([('tree/f1', 'A\nB\n'),
707
                                  ('tree/f2', 'A\nC\n'),
708
                                  ('tree/f3', 'A\nB\nC\n'),
709
                                 ])
710
        tree.commit('D', rev_id='D')
711
712
        # Switch to a read lock for this tree.
713
        # We still have addCleanup(unlock)
714
        tree.unlock()
715
        tree.lock_read()
716
        return tree
717
718
    def test_tree_with_single_merge(self):
719
        """Make sure the tree layout is correct."""
720
        tree = self.create_tree_with_single_merge()
721
        rev_A_tree = tree.branch.repository.revision_tree('A')
722
        rev_B_tree = tree.branch.repository.revision_tree('B')
723
724
        f1_changed = (u'f1', 'f1-id', 'file', True, False)
725
        f2_changed = (u'f2', 'f2-id', 'file', True, False)
726
        f3_changed = (u'f3', 'f3-id', 'file', True, False)
727
728
        delta = rev_B_tree.changes_from(rev_A_tree)
729
        self.assertEqual([f1_changed, f3_changed], delta.modified)
730
        self.assertEqual([], delta.renamed)
731
        self.assertEqual([], delta.added)
732
        self.assertEqual([], delta.removed)
733
734
        rev_C_tree = tree.branch.repository.revision_tree('C')
735
        delta = rev_C_tree.changes_from(rev_A_tree)
736
        self.assertEqual([f2_changed, f3_changed], delta.modified)
737
        self.assertEqual([], delta.renamed)
738
        self.assertEqual([], delta.added)
739
        self.assertEqual([], delta.removed)
740
741
        rev_D_tree = tree.branch.repository.revision_tree('D')
742
        delta = rev_D_tree.changes_from(rev_B_tree)
743
        self.assertEqual([f2_changed, f3_changed], delta.modified)
744
        self.assertEqual([], delta.renamed)
745
        self.assertEqual([], delta.added)
746
        self.assertEqual([], delta.removed)
747
748
        delta = rev_D_tree.changes_from(rev_C_tree)
749
        self.assertEqual([f1_changed, f3_changed], delta.modified)
750
        self.assertEqual([], delta.renamed)
751
        self.assertEqual([], delta.added)
752
        self.assertEqual([], delta.removed)
753
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
754
    def assertAllRevisionsForFileID(self, tree, file_id, revisions):
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
755
        """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
756
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
757
        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
758
        sure they are correct.
759
        """
760
        # The api for _get_revisions_touching_file_id is a little crazy,
761
        # So we do the setup here.
762
        mainline = tree.branch.revision_history()
763
        mainline.insert(0, None)
764
        revnos = dict((rev, idx+1) for idx, rev in enumerate(mainline))
765
        view_revs_iter = log.get_view_revisions(mainline, revnos, tree.branch,
766
                                                'reverse', True)
2466.12.1 by Kent Gibson
Fix ``bzr log -r`` to support selecting merge revisions.
767
        actual_revs = log._filter_revisions_touching_file_id(
768
                            tree.branch, 
769
                            file_id,
770
                            mainline,
771
                            list(view_revs_iter))
2359.1.7 by John Arbash Meinel
Create a direct test for _get_revisions_touching_file_id
772
        self.assertEqual(revisions, [r for r, revno, depth in actual_revs])
773
774
    def test_file_id_f1(self):
775
        tree = self.create_tree_with_single_merge()
776
        # f1 should be marked as modified by revisions A and B
777
        self.assertAllRevisionsForFileID(tree, 'f1-id', ['B', 'A'])
778
779
    def test_file_id_f2(self):
780
        tree = self.create_tree_with_single_merge()
781
        # f2 should be marked as modified by revisions A, C, and D
782
        # because D merged the changes from C.
783
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
784
785
    def test_file_id_f3(self):
786
        tree = self.create_tree_with_single_merge()
787
        # f3 should be marked as modified by revisions A, B, C, and D
788
        self.assertAllRevisionsForFileID(tree, 'f2-id', ['D', 'C', 'A'])
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
789
790
791
class TestShowChangedRevisions(TestCaseWithTransport):
792
793
    def test_show_changed_revisions_verbose(self):
794
        tree = self.make_branch_and_tree('tree_a')
795
        self.build_tree(['tree_a/foo'])
796
        tree.add('foo')
797
        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.
798
        s = self.make_utf8_encoded_stringio()
1551.17.2 by Aaron Bentley
Stop showing deltas in pull -v output
799
        log.show_changed_revisions(tree.branch, [], ['bar-id'], s)
800
        self.assertContainsRe(s.getvalue(), 'bar')
801
        self.assertNotContainsRe(s.getvalue(), 'foo')
2671.5.8 by Lukáš Lalinsky
Add tests for LogFormatter.short_committer and LogFormatter.short_author.
802
803
804
class TestLogFormatter(TestCase):
805
806
    def test_short_committer(self):
807
        rev = Revision('a-id')
808
        rev.committer = 'John Doe <jdoe@example.com>'
809
        lf = LogFormatter(None)
810
        self.assertEqual('John Doe', lf.short_committer(rev))
811
812
    def test_short_author(self):
813
        rev = Revision('a-id')
814
        rev.committer = 'John Doe <jdoe@example.com>'
815
        lf = LogFormatter(None)
816
        self.assertEqual('John Doe', lf.short_author(rev))
817
        rev.properties['author'] = 'John Smith <jsmith@example.com>'
818
        self.assertEqual('John Smith', lf.short_author(rev))