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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from cStringIO import StringIO
18
21
from bzrlib import (
27
from bzrlib.branch import Branch
28
from bzrlib.bzrdir import BzrDir
28
29
from bzrlib.lockdir import LockDir
29
30
from bzrlib.mutabletree import needs_tree_write_lock
31
from bzrlib.symbol_versioning import zero_thirteen
30
32
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
33
from bzrlib.transport import get_transport
31
34
from bzrlib.workingtree import (
63
66
class TestDefaultFormat(TestCaseWithTransport):
65
68
def test_get_set_default_format(self):
66
old_format = workingtree.format_registry.get_default()
68
self.assertTrue(isinstance(old_format, workingtree_4.WorkingTreeFormat6))
69
workingtree.format_registry.set_default(SampleTreeFormat())
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()
76
result = dir.create_workingtree()
77
self.assertEqual(result, 'A tree')
79
workingtree.format_registry.set_default(old_format)
80
self.assertEqual(old_format, workingtree.format_registry.get_default())
82
def test_get_set_default_format_by_key(self):
83
old_format = workingtree.format_registry.get_default()
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())
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()
96
result = dir.create_workingtree()
97
self.assertEqual(result, 'A tree')
99
workingtree.format_registry.set_default_key(
100
old_format.get_format_string())
101
self.assertEqual(old_format, workingtree.format_registry.get_default())
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)
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)
69
old_format = workingtree.WorkingTreeFormat.get_default_format()
71
self.assertTrue(isinstance(old_format, workingtree.WorkingTreeFormat3))
72
workingtree.WorkingTreeFormat.set_default_format(SampleTreeFormat())
74
# the default branch format is used by the meta dir format
75
# which is not the default bzrdir format at this point
76
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
77
dir.create_repository()
79
result = dir.create_workingtree()
80
self.assertEqual(result, 'A tree')
82
workingtree.WorkingTreeFormat.set_default_format(old_format)
83
self.assertEqual(old_format, workingtree.WorkingTreeFormat.get_default_format())
123
86
class SampleTreeFormat(workingtree.WorkingTreeFormat):
124
87
"""A sample format
126
this format is initializable, unsupported to aid in testing the
89
this format is initializable, unsupported to aid in testing the
127
90
open and open_downlevel routines.
145
107
return "opened tree."
148
class SampleExtraTreeFormat(workingtree.WorkingTreeFormat):
149
"""A sample format that does not support use in a metadir.
153
def get_format_string(self):
154
# Not usable in a metadir, so no format string
157
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
158
accelerator_tree=None, hardlink=False):
159
raise NotImplementedError(self.initialize)
161
def is_supported(self):
164
def open(self, transport, _found=False):
165
raise NotImplementedError(self.open)
168
110
class TestWorkingTreeFormat(TestCaseWithTransport):
169
111
"""Tests for the WorkingTreeFormat facility."""
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)
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))
184
113
def test_find_format(self):
185
114
# is the right format object found for a working tree?
186
115
# create a branch with a few known format objects.
220
149
format.initialize(dir)
221
150
# register a format for it.
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))
151
workingtree.WorkingTreeFormat.register_format(format)
227
152
# which branch.Open will refuse (not supported)
228
153
self.assertRaises(errors.UnsupportedFormatError, workingtree.WorkingTree.open, '.')
229
154
# but open_downlevel will work
230
155
self.assertEqual(format.open(dir), workingtree.WorkingTree.open_downlevel('.'))
231
156
# unregister the 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))
239
class TestWorkingTreeFormatRegistry(TestCase):
242
super(TestWorkingTreeFormatRegistry, self).setUp()
243
self.registry = workingtree.WorkingTreeFormatRegistry()
245
def test_register_unregister_format(self):
246
format = SampleTreeFormat()
247
self.registry.register(format)
248
self.assertEquals(format, self.registry.get("Sample tree format."))
249
self.registry.remove(format)
250
self.assertRaises(KeyError, self.registry.get, "Sample tree format.")
252
def test_get_all(self):
253
format = SampleTreeFormat()
254
self.assertEquals([], self.registry._get_all())
255
self.registry.register(format)
256
self.assertEquals([format], self.registry._get_all())
258
def test_register_extra(self):
259
format = SampleExtraTreeFormat()
260
self.assertEquals([], self.registry._get_all())
261
self.registry.register_extra(format)
262
self.assertEquals([format], self.registry._get_all())
264
def test_register_extra_lazy(self):
265
self.assertEquals([], self.registry._get_all())
266
self.registry.register_extra_lazy("bzrlib.tests.test_workingtree",
267
"SampleExtraTreeFormat")
268
formats = self.registry._get_all()
269
self.assertEquals(1, len(formats))
270
self.assertIsInstance(formats[0], SampleExtraTreeFormat)
157
workingtree.WorkingTreeFormat.unregister_format(format)
273
160
class TestWorkingTreeFormat3(TestCaseWithTransport):
328
215
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
329
216
control.create_repository()
330
217
control.create_branch()
331
tree = workingtree_3.WorkingTreeFormat3().initialize(control)
332
tree._transport.delete("pending-merges")
218
tree = workingtree.WorkingTreeFormat3().initialize(control)
219
tree._control_files._transport.delete("pending-merges")
333
220
self.assertEqual([], tree.get_parent_ids())
223
class TestFormat2WorkingTree(TestCaseWithTransport):
224
"""Tests that are specific to format 2 trees."""
226
def create_format2_tree(self, url):
227
return self.make_branch_and_tree(
228
url, format=bzrdir.BzrDirFormat6())
230
def test_conflicts(self):
231
# test backwards compatability
232
tree = self.create_format2_tree('.')
233
self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
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])
253
class TestNonFormatSpecificCode(TestCaseWithTransport):
254
"""This class contains tests of workingtree that are not format specific."""
256
def test_gen_file_id(self):
257
file_id = self.applyDeprecated(zero_thirteen, workingtree.gen_file_id,
259
self.assertStartsWith(file_id, 'filename-')
261
def test_gen_root_id(self):
262
file_id = self.applyDeprecated(zero_thirteen, workingtree.gen_root_id)
263
self.assertStartsWith(file_id, 'tree_root-')
336
266
class InstrumentedTree(object):
337
267
"""A instrumented tree to check the needs_tree_write_lock decorator."""
377
307
self.assertEqual(['t', 'u'], tree._locks)
378
308
self.assertRaises(TypeError, tree.method_that_raises, 'foo')
379
309
self.assertEqual(['t', 'u', 't', 'u'], tree._locks)
382
class TestRevert(TestCaseWithTransport):
384
def test_revert_conflicts_recursive(self):
385
this_tree = self.make_branch_and_tree('this-tree')
386
self.build_tree_contents([('this-tree/foo/',),
387
('this-tree/foo/bar', 'bar')])
388
this_tree.add(['foo', 'foo/bar'])
389
this_tree.commit('created foo/bar')
390
other_tree = this_tree.bzrdir.sprout('other-tree').open_workingtree()
391
self.build_tree_contents([('other-tree/foo/bar', 'baz')])
392
other_tree.commit('changed bar')
393
self.build_tree_contents([('this-tree/foo/bar', 'qux')])
394
this_tree.commit('changed qux')
395
this_tree.merge_from_branch(other_tree.branch)
396
self.assertEqual(1, len(this_tree.conflicts()))
397
this_tree.revert(['foo'])
398
self.assertEqual(0, len(this_tree.conflicts()))
401
class TestAutoResolve(TestCaseWithTransport):
403
def test_auto_resolve(self):
404
base = self.make_branch_and_tree('base')
405
self.build_tree_contents([('base/hello', 'Hello')])
406
base.add('hello', 'hello_id')
408
other = base.bzrdir.sprout('other').open_workingtree()
409
self.build_tree_contents([('other/hello', 'hELLO')])
410
other.commit('Case switch')
411
this = base.bzrdir.sprout('this').open_workingtree()
412
self.assertPathExists('this/hello')
413
self.build_tree_contents([('this/hello', 'Hello World')])
414
this.commit('Add World')
415
this.merge_from_branch(other.branch)
416
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
419
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
421
self.build_tree_contents([('this/hello', '<<<<<<<')])
423
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
425
self.build_tree_contents([('this/hello', '=======')])
427
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
429
self.build_tree_contents([('this/hello', '\n>>>>>>>')])
430
remaining, resolved = this.auto_resolve()
431
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
433
self.assertEqual([], resolved)
434
self.build_tree_contents([('this/hello', 'hELLO wORLD')])
435
remaining, resolved = this.auto_resolve()
436
self.assertEqual([], this.conflicts())
437
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
439
self.assertPathDoesNotExist('this/hello.BASE')
441
def test_auto_resolve_dir(self):
442
tree = self.make_branch_and_tree('tree')
443
self.build_tree(['tree/hello/'])
444
tree.add('hello', 'hello-id')
445
file_conflict = conflicts.TextConflict('file', 'hello-id')
446
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
450
class TestFindTrees(TestCaseWithTransport):
452
def test_find_trees(self):
453
self.make_branch_and_tree('foo')
454
self.make_branch_and_tree('foo/bar')
455
# Sticking a tree inside a control dir is heinous, so let's skip it
456
self.make_branch_and_tree('foo/.bzr/baz')
457
self.make_branch('qux')
458
trees = workingtree.WorkingTree.find_trees('.')
459
self.assertEqual(2, len(list(trees)))