~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_annotate.py

  • Committer: John Arbash Meinel
  • Date: 2007-03-01 21:56:19 UTC
  • mto: (2255.7.84 dirstate)
  • mto: This revision was merged to the branch mainline in revision 2322.
  • Revision ID: john@arbash-meinel.com-20070301215619-wpt6kz8yem3ypu1b
Update to dirstate locking.
Move all of WT4.lock_* functions locally, so that they can
properly interact and cleanup around when we lock/unlock the
dirstate file.
Change all Lock objects to be non-blocking. So that if someone
grabs a lock on the DirState we find out immediately, rather
than blocking.
Change WT4.unlock() so that if the dirstate is dirty, it will
save the contents even if it only has a read lock.
It does this by trying to take a write lock, if it fails
we just ignore it. If it succeeds, then we can flush to disk.
This is more important now that DirState tracks file changes.
It allows 'bzr status' to update the cached stat and sha values.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 Canonical Ltd
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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
"""Whitebox tests for annotate functionality."""
 
18
 
 
19
from cStringIO import StringIO
 
20
 
 
21
from bzrlib import (
 
22
    annotate,
 
23
    conflicts,
 
24
    errors,
 
25
    tests,
 
26
    trace,
 
27
    )
 
28
 
 
29
 
 
30
def annotation(text):
 
31
    return [tuple(l.split(' ', 1)) for l in text.splitlines(True)]
 
32
 
 
33
 
 
34
parent_1 = annotation("""\
 
35
rev1 a
 
36
rev2 b
 
37
rev3 c
 
38
rev4 d
 
39
rev5 e
 
40
""")
 
41
 
 
42
 
 
43
parent_2 = annotation("""\
 
44
rev1 a
 
45
rev3 c
 
46
rev4 d
 
47
rev6 f
 
48
rev7 e
 
49
rev8 h
 
50
""")
 
51
 
 
52
 
 
53
expected_2_1 = annotation("""\
 
54
rev1 a
 
55
blahblah b
 
56
rev3 c
 
57
rev4 d
 
58
rev7 e
 
59
""")
 
60
 
 
61
 
 
62
# a: in both, same value, kept
 
63
# b: in 1, kept
 
64
# c: in both, same value, kept
 
65
# d: in both, same value, kept
 
66
# e: 1 and 2 disagree, so it goes to blahblah
 
67
# f: in 2, but not in new, so ignored
 
68
# g: not in 1 or 2, so it goes to blahblah
 
69
# h: only in parent 2, so 2 gets it
 
70
expected_1_2_2 = annotation("""\
 
71
rev1 a
 
72
rev2 b
 
73
rev3 c
 
74
rev4 d
 
75
blahblah e
 
76
blahblah g
 
77
rev8 h
 
78
""")
 
79
 
 
80
 
 
81
new_1 = """\
 
82
a
 
83
b
 
84
c
 
85
d
 
86
e
 
87
""".splitlines(True)
 
88
 
 
89
 
 
90
new_2 = """\
 
91
a
 
92
b
 
93
c
 
94
d
 
95
e
 
96
g
 
97
h
 
98
""".splitlines(True)
 
99
 
 
100
 
 
101
class TestAnnotate(tests.TestCaseWithTransport):
 
102
 
 
103
    def create_merged_trees(self):
 
104
        """create 2 trees with merges between them.
 
105
 
 
106
        rev-1 --+
 
107
         |      |
 
108
        rev-2  rev-1_1_1
 
109
         |      |
 
110
         +------+
 
111
         |
 
112
        rev-3
 
113
        """
 
114
 
 
115
        tree1 = self.make_branch_and_tree('tree1')
 
116
        self.build_tree_contents([('tree1/a', 'first\n')])
 
117
        tree1.add(['a'], ['a-id'])
 
118
        tree1.commit('a', rev_id='rev-1',
 
119
                     committer="joe@foo.com",
 
120
                     timestamp=1166046000.00, timezone=0)
 
121
 
 
122
        tree2 = tree1.bzrdir.clone('tree2').open_workingtree()
 
123
 
 
124
        self.build_tree_contents([('tree1/a', 'first\nsecond\n')])
 
125
        tree1.commit('b', rev_id='rev-2',
 
126
                     committer='joe@foo.com',
 
127
                     timestamp=1166046001.00, timezone=0)
 
128
 
 
129
        self.build_tree_contents([('tree2/a', 'first\nthird\n')])
 
130
        tree2.commit('c', rev_id='rev-1_1_1',
 
131
                     committer="barry@foo.com",
 
132
                     timestamp=1166046002.00, timezone=0)
 
133
 
 
134
        num_conflicts = tree1.merge_from_branch(tree2.branch)
 
135
        self.assertEqual(1, num_conflicts)
 
136
 
 
137
        self.build_tree_contents([('tree1/a',
 
138
                                 'first\nsecond\nthird\n')])
 
139
        tree1.set_conflicts(conflicts.ConflictList())
 
140
        tree1.commit('merge 2', rev_id='rev-3',
 
141
                     committer='sal@foo.com',
 
142
                     timestamp=1166046003.00, timezone=0)
 
143
        return tree1, tree2
 
144
 
 
145
    def create_deeply_merged_trees(self):
 
146
        """Create some trees with a more complex merge history.
 
147
 
 
148
        rev-1 --+
 
149
         |      |
 
150
        rev-2  rev-1_1_1 --+
 
151
         |      |          |
 
152
         +------+          |
 
153
         |      |          |
 
154
        rev-3  rev-1_1_2  rev-1_1_1_1_1 --+
 
155
         |      |          |              |
 
156
         +------+          |              |
 
157
         |                 |              |
 
158
        rev-4             rev-1_1_1_1_2  rev-1_1_1_1_1_1_1
 
159
         |                 |              |
 
160
         +-----------------+              |
 
161
         |                                |
 
162
        rev-5                             |
 
163
         |                                |
 
164
         +--------------------------------+
 
165
         |
 
166
        rev-6
 
167
        """
 
168
        tree1, tree2 = self.create_merged_trees()
 
169
 
 
170
        tree3 = tree2.bzrdir.clone('tree3').open_workingtree()
 
171
 
 
172
        tree2.commit('noop', rev_id='rev-1_1_2')
 
173
        self.assertEqual(0, tree1.merge_from_branch(tree2.branch))
 
174
        tree1.commit('noop merge', rev_id='rev-4')
 
175
 
 
176
        self.build_tree_contents([('tree3/a', 'first\nthird\nfourth\n')])
 
177
        tree3.commit('four', rev_id='rev-1_1_1_1_1',
 
178
                     committer='jerry@foo.com',
 
179
                     timestamp=1166046003.00, timezone=0)
 
180
 
 
181
        tree4 = tree3.bzrdir.clone('tree4').open_workingtree()
 
182
 
 
183
        tree3.commit('noop', rev_id='rev-1_1_1_1_2',
 
184
                     committer='jerry@foo.com',
 
185
                     timestamp=1166046004.00, timezone=0)
 
186
        self.assertEqual(0, tree1.merge_from_branch(tree3.branch))
 
187
        tree1.commit('merge four', rev_id='rev-5')
 
188
 
 
189
        self.build_tree_contents([('tree4/a',
 
190
                                   'first\nthird\nfourth\nfifth\nsixth\n')])
 
191
        tree4.commit('five and six', rev_id='rev-1_1_1_1_1_1_1',
 
192
                     committer='george@foo.com',
 
193
                     timestamp=1166046005.00, timezone=0)
 
194
        self.assertEqual(0, tree1.merge_from_branch(tree4.branch))
 
195
        tree1.commit('merge five and six', rev_id='rev-6')
 
196
        return tree1
 
197
 
 
198
    def test_annotate_shows_dotted_revnos(self):
 
199
        tree1, tree2 = self.create_merged_trees()
 
200
 
 
201
        sio = StringIO()
 
202
        annotate.annotate_file(tree1.branch, 'rev-3', 'a-id',
 
203
                               to_file=sio)
 
204
        self.assertEqualDiff('1     joe@foo | first\n'
 
205
                             '2     joe@foo | second\n'
 
206
                             '1.1.1 barry@f | third\n',
 
207
                             sio.getvalue())
 
208
 
 
209
    def test_annotate_limits_dotted_revnos(self):
 
210
        """Annotate should limit dotted revnos to a depth of 12"""
 
211
        tree1 = self.create_deeply_merged_trees()
 
212
 
 
213
        sio = StringIO()
 
214
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
 
215
                               to_file=sio, verbose=False, full=False)
 
216
        self.assertEqualDiff('1            joe@foo | first\n'
 
217
                             '2            joe@foo | second\n'
 
218
                             '1.1.1        barry@f | third\n'
 
219
                             '1.1.1.1.1    jerry@f | fourth\n'
 
220
                             '1.1.1.1.1.1> george@ | fifth\n'
 
221
                             '                     | sixth\n',
 
222
                             sio.getvalue())
 
223
 
 
224
        sio = StringIO()
 
225
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
 
226
                               to_file=sio, verbose=False, full=True)
 
227
        self.assertEqualDiff('1            joe@foo | first\n'
 
228
                             '2            joe@foo | second\n'
 
229
                             '1.1.1        barry@f | third\n'
 
230
                             '1.1.1.1.1    jerry@f | fourth\n'
 
231
                             '1.1.1.1.1.1> george@ | fifth\n'
 
232
                             '1.1.1.1.1.1> george@ | sixth\n',
 
233
                             sio.getvalue())
 
234
 
 
235
        # verbose=True shows everything, the full revno, user id, and date
 
236
        sio = StringIO()
 
237
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
 
238
                               to_file=sio, verbose=True, full=False)
 
239
        self.assertEqualDiff('1             joe@foo.com    20061213 | first\n'
 
240
                             '2             joe@foo.com    20061213 | second\n'
 
241
                             '1.1.1         barry@foo.com  20061213 | third\n'
 
242
                             '1.1.1.1.1     jerry@foo.com  20061213 | fourth\n'
 
243
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | fifth\n'
 
244
                             '                                      | sixth\n',
 
245
                             sio.getvalue())
 
246
 
 
247
        sio = StringIO()
 
248
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
 
249
                               to_file=sio, verbose=True, full=True)
 
250
        self.assertEqualDiff('1             joe@foo.com    20061213 | first\n'
 
251
                             '2             joe@foo.com    20061213 | second\n'
 
252
                             '1.1.1         barry@foo.com  20061213 | third\n'
 
253
                             '1.1.1.1.1     jerry@foo.com  20061213 | fourth\n'
 
254
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | fifth\n'
 
255
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | sixth\n',
 
256
                             sio.getvalue())
 
257
 
 
258
    def test_annotate_uses_branch_context(self):
 
259
        """Dotted revnos should use the Branch context.
 
260
 
 
261
        When annotating a non-mainline revision, the annotation should still
 
262
        use dotted revnos from the mainline.
 
263
        """
 
264
        tree1 = self.create_deeply_merged_trees()
 
265
 
 
266
        sio = StringIO()
 
267
        annotate.annotate_file(tree1.branch, 'rev-1_1_1_1_1_1_1', 'a-id',
 
268
                               to_file=sio, verbose=False, full=False)
 
269
        self.assertEqualDiff('1            joe@foo | first\n'
 
270
                             '1.1.1        barry@f | third\n'
 
271
                             '1.1.1.1.1    jerry@f | fourth\n'
 
272
                             '1.1.1.1.1.1> george@ | fifth\n'
 
273
                             '                     | sixth\n',
 
274
                             sio.getvalue())
 
275
 
 
276
    def test_annotate_show_ids(self):
 
277
        tree1 = self.create_deeply_merged_trees()
 
278
 
 
279
        sio = StringIO()
 
280
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
 
281
                               to_file=sio, show_ids=True, full=False)
 
282
 
 
283
        # It looks better with real revision ids :)
 
284
        self.assertEqualDiff('            rev-1 | first\n'
 
285
                             '            rev-2 | second\n'
 
286
                             '        rev-1_1_1 | third\n'
 
287
                             '    rev-1_1_1_1_1 | fourth\n'
 
288
                             'rev-1_1_1_1_1_1_1 | fifth\n'
 
289
                             '                  | sixth\n',
 
290
                             sio.getvalue())
 
291
 
 
292
        sio = StringIO()
 
293
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
 
294
                               to_file=sio, show_ids=True, full=True)
 
295
 
 
296
        self.assertEqualDiff('            rev-1 | first\n'
 
297
                             '            rev-2 | second\n'
 
298
                             '        rev-1_1_1 | third\n'
 
299
                             '    rev-1_1_1_1_1 | fourth\n'
 
300
                             'rev-1_1_1_1_1_1_1 | fifth\n'
 
301
                             'rev-1_1_1_1_1_1_1 | sixth\n',
 
302
                             sio.getvalue())
 
303
 
 
304
 
 
305
class TestReannotate(tests.TestCase):
 
306
 
 
307
    def annotateEqual(self, expected, parents, newlines, revision_id):
 
308
        annotate_list = list(annotate.reannotate(parents, newlines,
 
309
                             revision_id))
 
310
        self.assertEqual(len(expected), len(annotate_list))
 
311
        for e, a in zip(expected, annotate_list):
 
312
            self.assertEqual(e, a)
 
313
 
 
314
    def test_reannotate(self):
 
315
        self.annotateEqual(parent_1, [parent_1], new_1, 'blahblah')
 
316
        self.annotateEqual(expected_2_1, [parent_2], new_1, 'blahblah')
 
317
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2, 
 
318
                           'blahblah')