~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_workingtree.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-08-17 18:13:57 UTC
  • mfrom: (5268.7.29 transport-segments)
  • Revision ID: pqm@pqm.ubuntu.com-20110817181357-y5q5eth1hk8bl3om
(jelmer) Allow specifying the colocated branch to use in the branch URL,
 and retrieving the branch name using ControlDir._get_selected_branch.
 (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
# Authors:  Robert Collins <robert.collins@canonical.com>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
13
13
#
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
18
 
from cStringIO import StringIO
19
 
import os
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
17
 
21
18
from bzrlib import (
22
19
    bzrdir,
23
20
    conflicts,
24
21
    errors,
 
22
    symbol_versioning,
 
23
    transport,
25
24
    workingtree,
 
25
    workingtree_3,
 
26
    workingtree_4,
26
27
    )
27
 
from bzrlib.branch import Branch
28
 
from bzrlib.bzrdir import BzrDir
29
28
from bzrlib.lockdir import LockDir
30
29
from bzrlib.mutabletree import needs_tree_write_lock
31
30
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
32
 
from bzrlib.transport import get_transport
33
31
from bzrlib.workingtree import (
34
32
    TreeEntry,
35
33
    TreeDirectory,
65
63
class TestDefaultFormat(TestCaseWithTransport):
66
64
 
67
65
    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())
 
66
        old_format = workingtree.format_registry.get_default()
 
67
        # default is 6
 
68
        self.assertTrue(isinstance(old_format, workingtree_4.WorkingTreeFormat6))
 
69
        workingtree.format_registry.set_default(SampleTreeFormat())
 
70
        try:
 
71
            # the default branch format is used by the meta dir format
 
72
            # which is not the default bzrdir format at this point
 
73
            dir = bzrdir.BzrDirMetaFormat1().initialize('.')
 
74
            dir.create_repository()
 
75
            dir.create_branch()
 
76
            result = dir.create_workingtree()
 
77
            self.assertEqual(result, 'A tree')
 
78
        finally:
 
79
            workingtree.format_registry.set_default(old_format)
 
80
        self.assertEqual(old_format, workingtree.format_registry.get_default())
 
81
 
 
82
    def test_get_set_default_format_by_key(self):
 
83
        old_format = workingtree.format_registry.get_default()
 
84
        # default is 6
 
85
        format = SampleTreeFormat()
 
86
        workingtree.format_registry.register(format)
 
87
        self.addCleanup(workingtree.format_registry.remove, format)
 
88
        self.assertTrue(isinstance(old_format, workingtree_4.WorkingTreeFormat6))
 
89
        workingtree.format_registry.set_default_key(format.get_format_string())
 
90
        try:
 
91
            # the default branch format is used by the meta dir format
 
92
            # which is not the default bzrdir format at this point
 
93
            dir = bzrdir.BzrDirMetaFormat1().initialize('.')
 
94
            dir.create_repository()
 
95
            dir.create_branch()
 
96
            result = dir.create_workingtree()
 
97
            self.assertEqual(result, 'A tree')
 
98
        finally:
 
99
            workingtree.format_registry.set_default_key(
 
100
                old_format.get_format_string())
 
101
        self.assertEqual(old_format, workingtree.format_registry.get_default())
 
102
 
 
103
    def test_open(self):
 
104
        tree = self.make_branch_and_tree('.')
 
105
        open_direct = workingtree.WorkingTree.open('.')
 
106
        self.assertEqual(tree.basedir, open_direct.basedir)
 
107
        open_no_args = workingtree.WorkingTree.open()
 
108
        self.assertEqual(tree.basedir, open_no_args.basedir)
 
109
 
 
110
    def test_open_containing(self):
 
111
        tree = self.make_branch_and_tree('.')
 
112
        open_direct, relpath = workingtree.WorkingTree.open_containing('.')
 
113
        self.assertEqual(tree.basedir, open_direct.basedir)
 
114
        self.assertEqual('', relpath)
 
115
        open_no_args, relpath = workingtree.WorkingTree.open_containing()
 
116
        self.assertEqual(tree.basedir, open_no_args.basedir)
 
117
        self.assertEqual('', relpath)
 
118
        open_subdir, relpath = workingtree.WorkingTree.open_containing('subdir')
 
119
        self.assertEqual(tree.basedir, open_subdir.basedir)
 
120
        self.assertEqual('subdir', relpath)
83
121
 
84
122
 
85
123
class SampleTreeFormat(workingtree.WorkingTreeFormat):
86
124
    """A sample format
87
125
 
88
 
    this format is initializable, unsupported to aid in testing the 
 
126
    this format is initializable, unsupported to aid in testing the
89
127
    open and open_downlevel routines.
90
128
    """
91
129
 
107
145
        return "opened tree."
108
146
 
109
147
 
 
148
class SampleExtraTreeFormat(workingtree.WorkingTreeFormat):
 
149
    """A sample format that does not support use in a metadir.
 
150
 
 
151
    """
 
152
 
 
153
    def get_format_string(self):
 
154
        # Not usable in a metadir, so no format string
 
155
        return None
 
156
 
 
157
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
 
158
                   accelerator_tree=None, hardlink=False):
 
159
        raise NotImplementedError(self.initialize)
 
160
 
 
161
    def is_supported(self):
 
162
        return False
 
163
 
 
164
    def open(self, transport, _found=False):
 
165
        raise NotImplementedError(self.open)
 
166
 
 
167
 
110
168
class TestWorkingTreeFormat(TestCaseWithTransport):
111
169
    """Tests for the WorkingTreeFormat facility."""
112
170
 
 
171
    def test_find_format_string(self):
 
172
        # is the right format object found for a working tree?
 
173
        branch = self.make_branch('branch')
 
174
        self.assertRaises(errors.NoWorkingTree,
 
175
            workingtree.WorkingTreeFormat.find_format_string, branch.bzrdir)
 
176
        transport = branch.bzrdir.get_workingtree_transport(None)
 
177
        transport.mkdir('.')
 
178
        transport.put_bytes("format", "some format name")
 
179
        # The format does not have to be known by Bazaar,
 
180
        # find_format_string just retrieves the name
 
181
        self.assertEquals("some format name",
 
182
            workingtree.WorkingTreeFormat.find_format_string(branch.bzrdir))
 
183
 
113
184
    def test_find_format(self):
114
185
        # is the right format object found for a working tree?
115
186
        # create a branch with a few known format objects.
119
190
            dir.create_repository()
120
191
            dir.create_branch()
121
192
            format.initialize(dir)
122
 
            t = get_transport(url)
 
193
            t = transport.get_transport(url)
123
194
            found_format = workingtree.WorkingTreeFormat.find_format(dir)
124
 
            self.failUnless(isinstance(found_format, format.__class__))
125
 
        check_format(workingtree.WorkingTreeFormat3(), "bar")
126
 
        
 
195
            self.assertIsInstance(found_format, format.__class__)
 
196
        check_format(workingtree_3.WorkingTreeFormat3(), "bar")
 
197
 
127
198
    def test_find_format_no_tree(self):
128
199
        dir = bzrdir.BzrDirMetaFormat1().initialize('.')
129
200
        self.assertRaises(errors.NoWorkingTree,
148
219
        # make a branch
149
220
        format.initialize(dir)
150
221
        # register a format for it.
151
 
        workingtree.WorkingTreeFormat.register_format(format)
 
222
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
223
            workingtree.WorkingTreeFormat.register_format, format)
 
224
        self.assertTrue(format in 
 
225
            self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
226
                workingtree.WorkingTreeFormat.get_formats))
152
227
        # which branch.Open will refuse (not supported)
153
228
        self.assertRaises(errors.UnsupportedFormatError, workingtree.WorkingTree.open, '.')
154
229
        # but open_downlevel will work
155
230
        self.assertEqual(format.open(dir), workingtree.WorkingTree.open_downlevel('.'))
156
231
        # unregister the format
157
 
        workingtree.WorkingTreeFormat.unregister_format(format)
 
232
        self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
233
            workingtree.WorkingTreeFormat.unregister_format, format)
 
234
        self.assertFalse(format in
 
235
            self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
 
236
                workingtree.WorkingTreeFormat.get_formats))
 
237
 
 
238
 
 
239
class TestWorkingTreeIterEntriesByDir_wSubtrees(TestCaseWithTransport):
 
240
 
 
241
    def make_simple_tree(self):
 
242
        tree = self.make_branch_and_tree('tree', format='development-subtree')
 
243
        self.build_tree(['tree/a/', 'tree/a/b/', 'tree/a/b/c'])
 
244
        tree.set_root_id('root-id')
 
245
        tree.add(['a', 'a/b', 'a/b/c'], ['a-id', 'b-id', 'c-id'])
 
246
        tree.commit('initial')
 
247
        return tree
 
248
 
 
249
    def test_just_directory(self):
 
250
        tree = self.make_simple_tree()
 
251
        self.assertEqual([('directory', 'root-id'),
 
252
                          ('directory', 'a-id'),
 
253
                          ('directory', 'b-id'),
 
254
                          ('file', 'c-id')],
 
255
                         [(ie.kind, ie.file_id)
 
256
                          for path, ie in tree.iter_entries_by_dir()])
 
257
        subtree = self.make_branch_and_tree('tree/a/b')
 
258
        self.assertEqual([('tree-reference', 'b-id')],
 
259
                         [(ie.kind, ie.file_id)
 
260
                          for path, ie in tree.iter_entries_by_dir(['b-id'])])
 
261
 
 
262
    def test_direct_subtree(self):
 
263
        tree = self.make_simple_tree()
 
264
        subtree = self.make_branch_and_tree('tree/a/b')
 
265
        self.assertEqual([('directory', 'root-id'),
 
266
                          ('directory', 'a-id'),
 
267
                          ('tree-reference', 'b-id')],
 
268
                         [(ie.kind, ie.file_id)
 
269
                          for path, ie in tree.iter_entries_by_dir()])
 
270
 
 
271
    def test_indirect_subtree(self):
 
272
        tree = self.make_simple_tree()
 
273
        subtree = self.make_branch_and_tree('tree/a')
 
274
        self.assertEqual([('directory', 'root-id'),
 
275
                          ('tree-reference', 'a-id')],
 
276
                         [(ie.kind, ie.file_id)
 
277
                          for path, ie in tree.iter_entries_by_dir()])
 
278
 
 
279
 
 
280
class TestWorkingTreeFormatRegistry(TestCase):
 
281
 
 
282
    def setUp(self):
 
283
        super(TestWorkingTreeFormatRegistry, self).setUp()
 
284
        self.registry = workingtree.WorkingTreeFormatRegistry()
 
285
 
 
286
    def test_register_unregister_format(self):
 
287
        format = SampleTreeFormat()
 
288
        self.registry.register(format)
 
289
        self.assertEquals(format, self.registry.get("Sample tree format."))
 
290
        self.registry.remove(format)
 
291
        self.assertRaises(KeyError, self.registry.get, "Sample tree format.")
 
292
 
 
293
    def test_get_all(self):
 
294
        format = SampleTreeFormat()
 
295
        self.assertEquals([], self.registry._get_all())
 
296
        self.registry.register(format)
 
297
        self.assertEquals([format], self.registry._get_all())
 
298
 
 
299
    def test_register_extra(self):
 
300
        format = SampleExtraTreeFormat()
 
301
        self.assertEquals([], self.registry._get_all())
 
302
        self.registry.register_extra(format)
 
303
        self.assertEquals([format], self.registry._get_all())
 
304
 
 
305
    def test_register_extra_lazy(self):
 
306
        self.assertEquals([], self.registry._get_all())
 
307
        self.registry.register_extra_lazy("bzrlib.tests.test_workingtree",
 
308
            "SampleExtraTreeFormat")
 
309
        formats = self.registry._get_all()
 
310
        self.assertEquals(1, len(formats))
 
311
        self.assertIsInstance(formats[0], SampleExtraTreeFormat)
158
312
 
159
313
 
160
314
class TestWorkingTreeFormat3(TestCaseWithTransport):
164
318
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
165
319
        control.create_repository()
166
320
        control.create_branch()
167
 
        tree = workingtree.WorkingTreeFormat3().initialize(control)
 
321
        tree = workingtree_3.WorkingTreeFormat3().initialize(control)
168
322
        # we want:
169
323
        # format 'Bazaar-NG Working Tree format 3'
170
324
        # inventory = blank inventory
174
328
        t = control.get_workingtree_transport(None)
175
329
        self.assertEqualDiff('Bazaar-NG Working Tree format 3',
176
330
                             t.get('format').read())
177
 
        self.assertEqualDiff(t.get('inventory').read(), 
 
331
        self.assertEqualDiff(t.get('inventory').read(),
178
332
                              '<inventory format="5">\n'
179
333
                              '</inventory>\n',
180
334
                             )
183
337
        self.assertFalse(t.has('inventory.basis'))
184
338
        # no last-revision file means 'None' or 'NULLREVISION'
185
339
        self.assertFalse(t.has('last-revision'))
186
 
        # TODO RBC 20060210 do a commit, check the inventory.basis is created 
 
340
        # TODO RBC 20060210 do a commit, check the inventory.basis is created
187
341
        # correctly and last-revision file becomes present.
188
342
 
189
343
    def test_uses_lockdir(self):
190
344
        """WorkingTreeFormat3 uses its own LockDir:
191
 
            
 
345
 
192
346
            - lock is a directory
193
347
            - when the WorkingTree is locked, LockDir can see that
194
348
        """
198
352
        repo = dir.create_repository()
199
353
        branch = dir.create_branch()
200
354
        try:
201
 
            tree = workingtree.WorkingTreeFormat3().initialize(dir)
 
355
            tree = workingtree_3.WorkingTreeFormat3().initialize(dir)
202
356
        except errors.NotLocalUrl:
203
357
            raise TestSkipped('Not a local URL')
204
358
        self.assertIsDirectory('.bzr', t)
215
369
        control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
216
370
        control.create_repository()
217
371
        control.create_branch()
218
 
        tree = workingtree.WorkingTreeFormat3().initialize(control)
 
372
        tree = workingtree_3.WorkingTreeFormat3().initialize(control)
219
373
        tree._transport.delete("pending-merges")
220
374
        self.assertEqual([], tree.get_parent_ids())
221
375
 
222
376
 
223
 
class TestFormat2WorkingTree(TestCaseWithTransport):
224
 
    """Tests that are specific to format 2 trees."""
225
 
 
226
 
    def create_format2_tree(self, url):
227
 
        return self.make_branch_and_tree(
228
 
            url, format=bzrdir.BzrDirFormat6())
229
 
 
230
 
    def test_conflicts(self):
231
 
        # test backwards compatability
232
 
        tree = self.create_format2_tree('.')
233
 
        self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
234
 
                          None)
235
 
        file('lala.BASE', 'wb').write('labase')
236
 
        expected = conflicts.ContentsConflict('lala')
237
 
        self.assertEqual(list(tree.conflicts()), [expected])
238
 
        file('lala', 'wb').write('la')
239
 
        tree.add('lala', 'lala-id')
240
 
        expected = conflicts.ContentsConflict('lala', file_id='lala-id')
241
 
        self.assertEqual(list(tree.conflicts()), [expected])
242
 
        file('lala.THIS', 'wb').write('lathis')
243
 
        file('lala.OTHER', 'wb').write('laother')
244
 
        # When "text conflict"s happen, stem, THIS and OTHER are text
245
 
        expected = conflicts.TextConflict('lala', file_id='lala-id')
246
 
        self.assertEqual(list(tree.conflicts()), [expected])
247
 
        os.unlink('lala.OTHER')
248
 
        os.mkdir('lala.OTHER')
249
 
        expected = conflicts.ContentsConflict('lala', file_id='lala-id')
250
 
        self.assertEqual(list(tree.conflicts()), [expected])
251
 
 
252
 
 
253
377
class InstrumentedTree(object):
254
378
    """A instrumented tree to check the needs_tree_write_lock decorator."""
255
379
 
267
391
    @needs_tree_write_lock
268
392
    def method_that_raises(self):
269
393
        """This method causes an exception when called with parameters.
270
 
        
 
394
 
271
395
        This allows the decorator code to be checked - it should still call
272
396
        unlock.
273
397
        """
284
408
        self.assertEqual(
285
409
            'method_with_tree_write_lock',
286
410
            tree.method_with_tree_write_lock.__name__)
287
 
        self.assertEqual(
 
411
        self.assertDocstring(
288
412
            "A lock_tree_write decorated method that returns its arguments.",
289
 
            tree.method_with_tree_write_lock.__doc__)
 
413
            tree.method_with_tree_write_lock)
290
414
        args = (1, 2, 3)
291
415
        kwargs = {'a':'b'}
292
416
        result = tree.method_with_tree_write_lock(1,2,3, a='b')
326
450
        self.build_tree_contents([('other/hello', 'hELLO')])
327
451
        other.commit('Case switch')
328
452
        this = base.bzrdir.sprout('this').open_workingtree()
329
 
        self.failUnlessExists('this/hello')
 
453
        self.assertPathExists('this/hello')
330
454
        self.build_tree_contents([('this/hello', 'Hello World')])
331
455
        this.commit('Add World')
332
456
        this.merge_from_branch(other.branch)
333
 
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
457
        self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
334
458
                         this.conflicts())
335
459
        this.auto_resolve()
336
 
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
460
        self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
337
461
                         this.conflicts())
338
462
        self.build_tree_contents([('this/hello', '<<<<<<<')])
339
463
        this.auto_resolve()
340
 
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
464
        self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
341
465
                         this.conflicts())
342
466
        self.build_tree_contents([('this/hello', '=======')])
343
467
        this.auto_resolve()
344
 
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
468
        self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
345
469
                         this.conflicts())
346
470
        self.build_tree_contents([('this/hello', '\n>>>>>>>')])
347
471
        remaining, resolved = this.auto_resolve()
348
 
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
472
        self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
349
473
                         this.conflicts())
350
474
        self.assertEqual([], resolved)
351
475
        self.build_tree_contents([('this/hello', 'hELLO wORLD')])
352
476
        remaining, resolved = this.auto_resolve()
353
477
        self.assertEqual([], this.conflicts())
354
 
        self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
 
478
        self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
355
479
                         resolved)
356
 
        self.failIfExists('this/hello.BASE')
 
480
        self.assertPathDoesNotExist('this/hello.BASE')
357
481
 
358
482
    def test_auto_resolve_dir(self):
359
483
        tree = self.make_branch_and_tree('tree')
360
484
        self.build_tree(['tree/hello/'])
361
485
        tree.add('hello', 'hello-id')
362
 
        file_conflict = conflicts.TextConflict('file', None, 'hello-id')
 
486
        file_conflict = conflicts.TextConflict('file', 'hello-id')
363
487
        tree.set_conflicts(conflicts.ConflictList([file_conflict]))
364
488
        tree.auto_resolve()
365
489