/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_workingtree.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-18 18:18:36 UTC
  • mto: This revision was merged to the branch mainline in revision 4461.
  • Revision ID: john@arbash-meinel.com-20090618181836-biodfkat9a8eyzjz
The new add_inventory_by_delta is returning a CHKInventory when mapping from NULL
Which is completely valid, but 'broke' one of the tests.
So to fix it, changed the test to use CHKInventories on both sides, and add an __eq__
member. The nice thing is that CHKInventory.__eq__ is fairly cheap, since it only
has to check the root keys.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
# Authors:  Robert Collins <robert.collins@canonical.com>
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 
 
18
from cStringIO import StringIO
 
19
import os
 
20
 
 
21
from bzrlib import (
 
22
    bzrdir,
 
23
    conflicts,
 
24
    errors,
 
25
    workingtree,
 
26
    )
 
27
from bzrlib.branch import Branch
 
28
from bzrlib.bzrdir import BzrDir
 
29
from bzrlib.lockdir import LockDir
 
30
from bzrlib.mutabletree import needs_tree_write_lock
 
31
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
 
32
from bzrlib.transport import get_transport
 
33
from bzrlib.workingtree import (
 
34
    TreeEntry,
 
35
    TreeDirectory,
 
36
    TreeFile,
 
37
    TreeLink,
 
38
    )
 
39
 
 
40
 
 
41
class TestTreeDirectory(TestCaseWithTransport):
 
42
 
 
43
    def test_kind_character(self):
 
44
        self.assertEqual(TreeDirectory().kind_character(), '/')
 
45
 
 
46
 
 
47
class TestTreeEntry(TestCaseWithTransport):
 
48
 
 
49
    def test_kind_character(self):
 
50
        self.assertEqual(TreeEntry().kind_character(), '???')
 
51
 
 
52
 
 
53
class TestTreeFile(TestCaseWithTransport):
 
54
 
 
55
    def test_kind_character(self):
 
56
        self.assertEqual(TreeFile().kind_character(), '')
 
57
 
 
58
 
 
59
class TestTreeLink(TestCaseWithTransport):
 
60
 
 
61
    def test_kind_character(self):
 
62
        self.assertEqual(TreeLink().kind_character(), '')
 
63
 
 
64
 
 
65
class TestDefaultFormat(TestCaseWithTransport):
 
66
 
 
67
    def test_get_set_default_format(self):
 
68
        old_format = workingtree.WorkingTreeFormat.get_default_format()
 
69
        # default is 3
 
70
        self.assertTrue(isinstance(old_format, workingtree.WorkingTreeFormat3))
 
71
        workingtree.WorkingTreeFormat.set_default_format(SampleTreeFormat())
 
72
        try:
 
73
            # the default branch format is used by the meta dir format
 
74
            # which is not the default bzrdir format at this point
 
75
            dir = bzrdir.BzrDirMetaFormat1().initialize('.')
 
76
            dir.create_repository()
 
77
            dir.create_branch()
 
78
            result = dir.create_workingtree()
 
79
            self.assertEqual(result, 'A tree')
 
80
        finally:
 
81
            workingtree.WorkingTreeFormat.set_default_format(old_format)
 
82
        self.assertEqual(old_format, workingtree.WorkingTreeFormat.get_default_format())
 
83
 
 
84
    def test_open(self):
 
85
        tree = self.make_branch_and_tree('.')
 
86
        open_direct = workingtree.WorkingTree.open('.')
 
87
        self.assertEqual(tree.basedir, open_direct.basedir)
 
88
        open_no_args = workingtree.WorkingTree.open()
 
89
        self.assertEqual(tree.basedir, open_no_args.basedir)
 
90
 
 
91
    def test_open_containing(self):
 
92
        tree = self.make_branch_and_tree('.')
 
93
        open_direct, relpath = workingtree.WorkingTree.open_containing('.')
 
94
        self.assertEqual(tree.basedir, open_direct.basedir)
 
95
        self.assertEqual('', relpath)
 
96
        open_no_args, relpath = workingtree.WorkingTree.open_containing()
 
97
        self.assertEqual(tree.basedir, open_no_args.basedir)
 
98
        self.assertEqual('', relpath)
 
99
        open_subdir, relpath = workingtree.WorkingTree.open_containing('subdir')
 
100
        self.assertEqual(tree.basedir, open_subdir.basedir)
 
101
        self.assertEqual('subdir', relpath)
 
102
 
 
103
 
 
104
class SampleTreeFormat(workingtree.WorkingTreeFormat):
 
105
    """A sample format
 
106
 
 
107
    this format is initializable, unsupported to aid in testing the
 
108
    open and open_downlevel routines.
 
109
    """
 
110
 
 
111
    def get_format_string(self):
 
112
        """See WorkingTreeFormat.get_format_string()."""
 
113
        return "Sample tree format."
 
114
 
 
115
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
116
                   accelerator_tree=None, hardlink=False):
 
117
        """Sample branches cannot be created."""
 
118
        t = a_bzrdir.get_workingtree_transport(self)
 
119
        t.put_bytes('format', self.get_format_string())
 
120
        return 'A tree'
 
121
 
 
122
    def is_supported(self):
 
123
        return False
 
124
 
 
125
    def open(self, transport, _found=False):
 
126
        return "opened tree."
 
127
 
 
128
 
 
129
class TestWorkingTreeFormat(TestCaseWithTransport):
 
130
    """Tests for the WorkingTreeFormat facility."""
 
131
 
 
132
    def test_find_format(self):
 
133
        # is the right format object found for a working tree?
 
134
        # create a branch with a few known format objects.
 
135
        self.build_tree(["foo/", "bar/"])
 
136
        def check_format(format, url):
 
137
            dir = format._matchingbzrdir.initialize(url)
 
138
            dir.create_repository()
 
139
            dir.create_branch()
 
140
            format.initialize(dir)
 
141
            t = get_transport(url)
 
142
            found_format = workingtree.WorkingTreeFormat.find_format(dir)
 
143
            self.failUnless(isinstance(found_format, format.__class__))
 
144
        check_format(workingtree.WorkingTreeFormat3(), "bar")
 
145
 
 
146
    def test_find_format_no_tree(self):
 
147
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
 
148
        self.assertRaises(errors.NoWorkingTree,
 
149
                          workingtree.WorkingTreeFormat.find_format,
 
150
                          dir)
 
151
 
 
152
    def test_find_format_unknown_format(self):
 
153
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
 
154
        dir.create_repository()
 
155
        dir.create_branch()
 
156
        SampleTreeFormat().initialize(dir)
 
157
        self.assertRaises(errors.UnknownFormatError,
 
158
                          workingtree.WorkingTreeFormat.find_format,
 
159
                          dir)
 
160
 
 
161
    def test_register_unregister_format(self):
 
162
        format = SampleTreeFormat()
 
163
        # make a control dir
 
164
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
 
165
        dir.create_repository()
 
166
        dir.create_branch()
 
167
        # make a branch
 
168
        format.initialize(dir)
 
169
        # register a format for it.
 
170
        workingtree.WorkingTreeFormat.register_format(format)
 
171
        # which branch.Open will refuse (not supported)
 
172
        self.assertRaises(errors.UnsupportedFormatError, workingtree.WorkingTree.open, '.')
 
173
        # but open_downlevel will work
 
174
        self.assertEqual(format.open(dir), workingtree.WorkingTree.open_downlevel('.'))
 
175
        # unregister the format
 
176
        workingtree.WorkingTreeFormat.unregister_format(format)
 
177
 
 
178
 
 
179
class TestWorkingTreeFormat3(TestCaseWithTransport):
 
180
    """Tests specific to WorkingTreeFormat3."""
 
181
 
 
182
    def test_disk_layout(self):
 
183
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
184
        control.create_repository()
 
185
        control.create_branch()
 
186
        tree = workingtree.WorkingTreeFormat3().initialize(control)
 
187
        # we want:
 
188
        # format 'Bazaar-NG Working Tree format 3'
 
189
        # inventory = blank inventory
 
190
        # pending-merges = ''
 
191
        # stat-cache = ??
 
192
        # no inventory.basis yet
 
193
        t = control.get_workingtree_transport(None)
 
194
        self.assertEqualDiff('Bazaar-NG Working Tree format 3',
 
195
                             t.get('format').read())
 
196
        self.assertEqualDiff(t.get('inventory').read(),
 
197
                              '<inventory format="5">\n'
 
198
                              '</inventory>\n',
 
199
                             )
 
200
        self.assertEqualDiff('### bzr hashcache v5\n',
 
201
                             t.get('stat-cache').read())
 
202
        self.assertFalse(t.has('inventory.basis'))
 
203
        # no last-revision file means 'None' or 'NULLREVISION'
 
204
        self.assertFalse(t.has('last-revision'))
 
205
        # TODO RBC 20060210 do a commit, check the inventory.basis is created
 
206
        # correctly and last-revision file becomes present.
 
207
 
 
208
    def test_uses_lockdir(self):
 
209
        """WorkingTreeFormat3 uses its own LockDir:
 
210
 
 
211
            - lock is a directory
 
212
            - when the WorkingTree is locked, LockDir can see that
 
213
        """
 
214
        t = self.get_transport()
 
215
        url = self.get_url()
 
216
        dir = bzrdir.BzrDirMetaFormat1().initialize(url)
 
217
        repo = dir.create_repository()
 
218
        branch = dir.create_branch()
 
219
        try:
 
220
            tree = workingtree.WorkingTreeFormat3().initialize(dir)
 
221
        except errors.NotLocalUrl:
 
222
            raise TestSkipped('Not a local URL')
 
223
        self.assertIsDirectory('.bzr', t)
 
224
        self.assertIsDirectory('.bzr/checkout', t)
 
225
        self.assertIsDirectory('.bzr/checkout/lock', t)
 
226
        our_lock = LockDir(t, '.bzr/checkout/lock')
 
227
        self.assertEquals(our_lock.peek(), None)
 
228
        tree.lock_write()
 
229
        self.assertTrue(our_lock.peek())
 
230
        tree.unlock()
 
231
        self.assertEquals(our_lock.peek(), None)
 
232
 
 
233
    def test_missing_pending_merges(self):
 
234
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
 
235
        control.create_repository()
 
236
        control.create_branch()
 
237
        tree = workingtree.WorkingTreeFormat3().initialize(control)
 
238
        tree._transport.delete("pending-merges")
 
239
        self.assertEqual([], tree.get_parent_ids())
 
240
 
 
241
 
 
242
class TestFormat2WorkingTree(TestCaseWithTransport):
 
243
    """Tests that are specific to format 2 trees."""
 
244
 
 
245
    def create_format2_tree(self, url):
 
246
        return self.make_branch_and_tree(
 
247
            url, format=bzrdir.BzrDirFormat6())
 
248
 
 
249
    def test_conflicts(self):
 
250
        # test backwards compatability
 
251
        tree = self.create_format2_tree('.')
 
252
        self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
 
253
                          None)
 
254
        file('lala.BASE', 'wb').write('labase')
 
255
        expected = conflicts.ContentsConflict('lala')
 
256
        self.assertEqual(list(tree.conflicts()), [expected])
 
257
        file('lala', 'wb').write('la')
 
258
        tree.add('lala', 'lala-id')
 
259
        expected = conflicts.ContentsConflict('lala', file_id='lala-id')
 
260
        self.assertEqual(list(tree.conflicts()), [expected])
 
261
        file('lala.THIS', 'wb').write('lathis')
 
262
        file('lala.OTHER', 'wb').write('laother')
 
263
        # When "text conflict"s happen, stem, THIS and OTHER are text
 
264
        expected = conflicts.TextConflict('lala', file_id='lala-id')
 
265
        self.assertEqual(list(tree.conflicts()), [expected])
 
266
        os.unlink('lala.OTHER')
 
267
        os.mkdir('lala.OTHER')
 
268
        expected = conflicts.ContentsConflict('lala', file_id='lala-id')
 
269
        self.assertEqual(list(tree.conflicts()), [expected])
 
270
 
 
271
 
 
272
class InstrumentedTree(object):
 
273
    """A instrumented tree to check the needs_tree_write_lock decorator."""
 
274
 
 
275
    def __init__(self):
 
276
        self._locks = []
 
277
 
 
278
    def lock_tree_write(self):
 
279
        self._locks.append('t')
 
280
 
 
281
    @needs_tree_write_lock
 
282
    def method_with_tree_write_lock(self, *args, **kwargs):
 
283
        """A lock_tree_write decorated method that returns its arguments."""
 
284
        return args, kwargs
 
285
 
 
286
    @needs_tree_write_lock
 
287
    def method_that_raises(self):
 
288
        """This method causes an exception when called with parameters.
 
289
 
 
290
        This allows the decorator code to be checked - it should still call
 
291
        unlock.
 
292
        """
 
293
 
 
294
    def unlock(self):
 
295
        self._locks.append('u')
 
296
 
 
297
 
 
298
class TestInstrumentedTree(TestCase):
 
299
 
 
300
    def test_needs_tree_write_lock(self):
 
301
        """@needs_tree_write_lock should be semantically transparent."""
 
302
        tree = InstrumentedTree()
 
303
        self.assertEqual(
 
304
            'method_with_tree_write_lock',
 
305
            tree.method_with_tree_write_lock.__name__)
 
306
        self.assertEqual(
 
307
            "A lock_tree_write decorated method that returns its arguments.",
 
308
            tree.method_with_tree_write_lock.__doc__)
 
309
        args = (1, 2, 3)
 
310
        kwargs = {'a':'b'}
 
311
        result = tree.method_with_tree_write_lock(1,2,3, a='b')
 
312
        self.assertEqual((args, kwargs), result)
 
313
        self.assertEqual(['t', 'u'], tree._locks)
 
314
        self.assertRaises(TypeError, tree.method_that_raises, 'foo')
 
315
        self.assertEqual(['t', 'u', 't', 'u'], tree._locks)
 
316
 
 
317
 
 
318
class TestRevert(TestCaseWithTransport):
 
319
 
 
320
    def test_revert_conflicts_recursive(self):
 
321
        this_tree = self.make_branch_and_tree('this-tree')
 
322
        self.build_tree_contents([('this-tree/foo/',),
 
323
                                  ('this-tree/foo/bar', 'bar')])
 
324
        this_tree.add(['foo', 'foo/bar'])
 
325
        this_tree.commit('created foo/bar')
 
326
        other_tree = this_tree.bzrdir.sprout('other-tree').open_workingtree()
 
327
        self.build_tree_contents([('other-tree/foo/bar', 'baz')])
 
328
        other_tree.commit('changed bar')
 
329
        self.build_tree_contents([('this-tree/foo/bar', 'qux')])
 
330
        this_tree.commit('changed qux')
 
331
        this_tree.merge_from_branch(other_tree.branch)
 
332
        self.assertEqual(1, len(this_tree.conflicts()))
 
333
        this_tree.revert(['foo'])
 
334
        self.assertEqual(0, len(this_tree.conflicts()))
 
335
 
 
336
 
 
337
class TestAutoResolve(TestCaseWithTransport):
 
338
 
 
339
    def test_auto_resolve(self):
 
340
        base = self.make_branch_and_tree('base')
 
341
        self.build_tree_contents([('base/hello', 'Hello')])
 
342
        base.add('hello', 'hello_id')
 
343
        base.commit('Hello')
 
344
        other = base.bzrdir.sprout('other').open_workingtree()
 
345
        self.build_tree_contents([('other/hello', 'hELLO')])
 
346
        other.commit('Case switch')
 
347
        this = base.bzrdir.sprout('this').open_workingtree()
 
348
        self.failUnlessExists('this/hello')
 
349
        self.build_tree_contents([('this/hello', 'Hello World')])
 
350
        this.commit('Add World')
 
351
        this.merge_from_branch(other.branch)
 
352
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
353
                         this.conflicts())
 
354
        this.auto_resolve()
 
355
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
356
                         this.conflicts())
 
357
        self.build_tree_contents([('this/hello', '<<<<<<<')])
 
358
        this.auto_resolve()
 
359
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
360
                         this.conflicts())
 
361
        self.build_tree_contents([('this/hello', '=======')])
 
362
        this.auto_resolve()
 
363
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
364
                         this.conflicts())
 
365
        self.build_tree_contents([('this/hello', '\n>>>>>>>')])
 
366
        remaining, resolved = this.auto_resolve()
 
367
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
368
                         this.conflicts())
 
369
        self.assertEqual([], resolved)
 
370
        self.build_tree_contents([('this/hello', 'hELLO wORLD')])
 
371
        remaining, resolved = this.auto_resolve()
 
372
        self.assertEqual([], this.conflicts())
 
373
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
374
                         resolved)
 
375
        self.failIfExists('this/hello.BASE')
 
376
 
 
377
    def test_auto_resolve_dir(self):
 
378
        tree = self.make_branch_and_tree('tree')
 
379
        self.build_tree(['tree/hello/'])
 
380
        tree.add('hello', 'hello-id')
 
381
        file_conflict = conflicts.TextConflict('file', None, 'hello-id')
 
382
        tree.set_conflicts(conflicts.ConflictList([file_conflict]))
 
383
        tree.auto_resolve()
 
384
 
 
385
 
 
386
class TestFindTrees(TestCaseWithTransport):
 
387
 
 
388
    def test_find_trees(self):
 
389
        self.make_branch_and_tree('foo')
 
390
        self.make_branch_and_tree('foo/bar')
 
391
        # Sticking a tree inside a control dir is heinous, so let's skip it
 
392
        self.make_branch_and_tree('foo/.bzr/baz')
 
393
        self.make_branch('qux')
 
394
        trees = workingtree.WorkingTree.find_trees('.')
 
395
        self.assertEqual(2, len(list(trees)))