192
182
def test_find_format_string(self):
193
183
# is the right format object found for a working tree?
194
184
branch = self.make_branch('branch')
196
errors.NoWorkingTree,
197
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string,
185
self.assertRaises(errors.NoWorkingTree,
186
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string, branch.controldir)
199
187
transport = branch.controldir.get_workingtree_transport(None)
200
188
transport.mkdir('.')
201
transport.put_bytes("format", b"some format name")
189
transport.put_bytes("format", "some format name")
202
190
# The format does not have to be known by Bazaar,
203
191
# find_format_string just retrieves the name
206
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string(
192
self.assertEqual("some format name",
193
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string(branch.controldir))
209
195
def test_find_format(self):
210
196
# is the right format object found for a working tree?
211
197
# create a branch with a few known format objects.
212
198
self.build_tree(["foo/", "bar/"])
214
199
def check_format(format, url):
215
dir = format._matchingcontroldir.initialize(url)
200
dir = format._matchingbzrdir.initialize(url)
216
201
dir.create_repository()
217
202
dir.create_branch()
218
203
format.initialize(dir)
219
found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(
204
t = transport.get_transport(url)
205
found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(dir)
221
206
self.assertIsInstance(found_format, format.__class__)
222
207
check_format(workingtree_3.WorkingTreeFormat3(), "bar")
257
241
def make_simple_tree(self):
258
242
tree = self.make_branch_and_tree('tree', format='development-subtree')
259
243
self.build_tree(['tree/a/', 'tree/a/b/', 'tree/a/b/c'])
260
tree.set_root_id(b'root-id')
261
tree.add(['a', 'a/b', 'a/b/c'], [b'a-id', b'b-id', b'c-id'])
244
tree.set_root_id('root-id')
245
tree.add(['a', 'a/b', 'a/b/c'], ['a-id', 'b-id', 'c-id'])
262
246
tree.commit('initial')
265
249
def test_just_directory(self):
266
250
tree = self.make_simple_tree()
267
self.assertEqual([('directory', b'root-id'),
268
('directory', b'a-id'),
269
('directory', b'b-id'),
251
self.assertEqual([('directory', 'root-id'),
252
('directory', 'a-id'),
253
('directory', 'b-id'),
271
255
[(ie.kind, ie.file_id)
272
256
for path, ie in tree.iter_entries_by_dir()])
273
self.make_branch_and_tree('tree/a/b')
274
self.assertEqual([('tree-reference', b'b-id')],
257
subtree = self.make_branch_and_tree('tree/a/b')
258
self.assertEqual([('tree-reference', 'b-id')],
275
259
[(ie.kind, ie.file_id)
276
for path, ie in tree.iter_entries_by_dir(
277
specific_files=['a/b'])])
260
for path, ie in tree.iter_entries_by_dir(['b-id'])])
279
262
def test_direct_subtree(self):
280
263
tree = self.make_simple_tree()
281
self.make_branch_and_tree('tree/a/b')
282
self.assertEqual([('directory', b'root-id'),
283
('directory', b'a-id'),
284
('tree-reference', b'b-id')],
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')],
285
268
[(ie.kind, ie.file_id)
286
269
for path, ie in tree.iter_entries_by_dir()])
288
271
def test_indirect_subtree(self):
289
272
tree = self.make_simple_tree()
290
self.make_branch_and_tree('tree/a')
291
self.assertEqual([('directory', b'root-id'),
292
('tree-reference', b'a-id')],
273
subtree = self.make_branch_and_tree('tree/a')
274
self.assertEqual([('directory', 'root-id'),
275
('tree-reference', 'a-id')],
293
276
[(ie.kind, ie.file_id)
294
277
for path, ie in tree.iter_entries_by_dir()])
390
374
self.assertEqual([], tree.get_parent_ids())
377
class InstrumentedTree(object):
378
"""A instrumented tree to check the needs_tree_write_lock decorator."""
383
def lock_tree_write(self):
384
self._locks.append('t')
386
@needs_tree_write_lock
387
def method_with_tree_write_lock(self, *args, **kwargs):
388
"""A lock_tree_write decorated method that returns its arguments."""
391
@needs_tree_write_lock
392
def method_that_raises(self):
393
"""This method causes an exception when called with parameters.
395
This allows the decorator code to be checked - it should still call
400
self._locks.append('u')
403
class TestInstrumentedTree(TestCase):
405
def test_needs_tree_write_lock(self):
406
"""@needs_tree_write_lock should be semantically transparent."""
407
tree = InstrumentedTree()
409
'method_with_tree_write_lock',
410
tree.method_with_tree_write_lock.__name__)
411
self.assertDocstring(
412
"A lock_tree_write decorated method that returns its arguments.",
413
tree.method_with_tree_write_lock)
416
result = tree.method_with_tree_write_lock(1,2,3, a='b')
417
self.assertEqual((args, kwargs), result)
418
self.assertEqual(['t', 'u'], tree._locks)
419
self.assertRaises(TypeError, tree.method_that_raises, 'foo')
420
self.assertEqual(['t', 'u', 't', 'u'], tree._locks)
393
423
class TestRevert(TestCaseWithTransport):
395
425
def test_revert_conflicts_recursive(self):
396
426
this_tree = self.make_branch_and_tree('this-tree')
397
427
self.build_tree_contents([('this-tree/foo/',),
398
('this-tree/foo/bar', b'bar')])
428
('this-tree/foo/bar', 'bar')])
399
429
this_tree.add(['foo', 'foo/bar'])
400
430
this_tree.commit('created foo/bar')
401
other_tree = this_tree.controldir.sprout(
402
'other-tree').open_workingtree()
403
self.build_tree_contents([('other-tree/foo/bar', b'baz')])
431
other_tree = this_tree.controldir.sprout('other-tree').open_workingtree()
432
self.build_tree_contents([('other-tree/foo/bar', 'baz')])
404
433
other_tree.commit('changed bar')
405
self.build_tree_contents([('this-tree/foo/bar', b'qux')])
434
self.build_tree_contents([('this-tree/foo/bar', 'qux')])
406
435
this_tree.commit('changed qux')
407
436
this_tree.merge_from_branch(other_tree.branch)
408
437
self.assertEqual(1, len(this_tree.conflicts()))
413
442
class TestAutoResolve(TestCaseWithTransport):
415
def _auto_resolve(self, tree):
416
"""Call auto_resolve on tree expecting deprecation"""
417
return self.applyDeprecated(
418
symbol_versioning.deprecated_in((3, 0, 1)),
421
444
def test_auto_resolve(self):
422
445
base = self.make_branch_and_tree('base')
423
self.build_tree_contents([('base/hello', b'Hello')])
424
base.add('hello', b'hello_id')
446
self.build_tree_contents([('base/hello', 'Hello')])
447
base.add('hello', 'hello_id')
425
448
base.commit('Hello')
426
449
other = base.controldir.sprout('other').open_workingtree()
427
self.build_tree_contents([('other/hello', b'hELLO')])
450
self.build_tree_contents([('other/hello', 'hELLO')])
428
451
other.commit('Case switch')
429
452
this = base.controldir.sprout('this').open_workingtree()
430
453
self.assertPathExists('this/hello')
431
self.build_tree_contents([('this/hello', b'Hello World')])
454
self.build_tree_contents([('this/hello', 'Hello World')])
432
455
this.commit('Add World')
433
456
this.merge_from_branch(other.branch)
434
self.assertEqual([_mod_bzr_conflicts.TextConflict('hello', b'hello_id')],
457
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
435
458
this.conflicts())
436
self._auto_resolve(this)
437
self.assertEqual([_mod_bzr_conflicts.TextConflict('hello', b'hello_id')],
460
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
438
461
this.conflicts())
439
462
self.build_tree_contents([('this/hello', '<<<<<<<')])
440
self._auto_resolve(this)
441
self.assertEqual([_mod_bzr_conflicts.TextConflict('hello', b'hello_id')],
464
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
442
465
this.conflicts())
443
466
self.build_tree_contents([('this/hello', '=======')])
444
self._auto_resolve(this)
445
self.assertEqual([_mod_bzr_conflicts.TextConflict('hello', b'hello_id')],
468
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
446
469
this.conflicts())
447
470
self.build_tree_contents([('this/hello', '\n>>>>>>>')])
448
remaining, resolved = self._auto_resolve(this)
449
self.assertEqual([_mod_bzr_conflicts.TextConflict('hello', b'hello_id')],
471
remaining, resolved = this.auto_resolve()
472
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
450
473
this.conflicts())
451
474
self.assertEqual([], resolved)
452
self.build_tree_contents([('this/hello', b'hELLO wORLD')])
453
remaining, resolved = self._auto_resolve(this)
475
self.build_tree_contents([('this/hello', 'hELLO wORLD')])
476
remaining, resolved = this.auto_resolve()
454
477
self.assertEqual([], this.conflicts())
455
self.assertEqual([_mod_bzr_conflicts.TextConflict('hello', b'hello_id')],
478
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
457
480
self.assertPathDoesNotExist('this/hello.BASE')
459
def test_unsupported_symlink_auto_resolve(self):
460
self.requireFeature(SymlinkFeature)
461
base = self.make_branch_and_tree('base')
462
self.build_tree_contents([('base/hello', 'Hello')])
463
base.add('hello', b'hello_id')
464
base.commit('commit 0')
465
other = base.controldir.sprout('other').open_workingtree()
466
self.build_tree_contents([('other/hello', 'Hello')])
467
os.symlink('other/hello', 'other/foo')
468
other.add('foo', b'foo_id')
469
other.commit('commit symlink')
470
this = base.controldir.sprout('this').open_workingtree()
471
self.assertPathExists('this/hello')
472
self.build_tree_contents([('this/hello', 'Hello')])
473
this.commit('commit 2')
475
trace.push_log_file(log)
476
os_symlink = getattr(os, 'symlink', None)
479
this.merge_from_branch(other.branch)
482
os.symlink = os_symlink
483
self.assertContainsRe(
485
b'Unable to create symlink "foo" on this filesystem')
487
482
def test_auto_resolve_dir(self):
488
483
tree = self.make_branch_and_tree('tree')
489
484
self.build_tree(['tree/hello/'])
490
tree.add('hello', b'hello-id')
491
file_conflict = _mod_bzr_conflicts.TextConflict('hello', b'hello-id')
492
tree.set_conflicts([file_conflict])
493
remaining, resolved = self._auto_resolve(tree)
496
conflicts.ConflictList([_mod_bzr_conflicts.TextConflict(u'hello', 'hello-id')]))
497
self.assertEqual(resolved, [])
499
def test_auto_resolve_missing(self):
500
tree = self.make_branch_and_tree('tree')
501
file_conflict = _mod_bzr_conflicts.TextConflict('hello', b'hello-id')
502
tree.set_conflicts([file_conflict])
503
remaining, resolved = self._auto_resolve(tree)
504
self.assertEqual(remaining, [])
507
conflicts.ConflictList([_mod_bzr_conflicts.TextConflict(u'hello', 'hello-id')]))
485
tree.add('hello', 'hello-id')
486
file_conflict = conflicts.TextConflict('file', 'hello-id')
487
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
491
class TestFindTrees(TestCaseWithTransport):
493
def test_find_trees(self):
494
self.make_branch_and_tree('foo')
495
self.make_branch_and_tree('foo/bar')
496
# Sticking a tree inside a control dir is heinous, so let's skip it
497
self.make_branch_and_tree('foo/.bzr/baz')
498
self.make_branch('qux')
499
trees = workingtree.WorkingTree.find_trees('.')
500
self.assertEqual(2, len(list(trees)))
510
503
class TestStoredUncommitted(TestCaseWithTransport):