206
212
self.assertEquals(our_lock.peek(), None)
214
def test_missing_pending_merges(self):
215
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
216
control.create_repository()
217
control.create_branch()
218
tree = workingtree.WorkingTreeFormat3().initialize(control)
219
tree._transport.delete("pending-merges")
220
self.assertEqual([], tree.get_parent_ids())
223
class TestFormat2WorkingTree(TestCaseWithTransport):
224
"""Tests that are specific to format 2 trees."""
208
226
def create_format2_tree(self, url):
209
return BzrDir.create_standalone_workingtree(url)
227
return self.make_branch_and_tree(
228
url, format=bzrdir.BzrDirFormat6())
211
def test_conflicts_format2(self):
230
def test_conflicts(self):
212
231
# test backwards compatability
213
232
tree = self.create_format2_tree('.')
214
233
self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
216
235
file('lala.BASE', 'wb').write('labase')
217
expected = ContentsConflict('lala')
236
expected = conflicts.ContentsConflict('lala')
218
237
self.assertEqual(list(tree.conflicts()), [expected])
219
238
file('lala', 'wb').write('la')
220
239
tree.add('lala', 'lala-id')
221
expected = ContentsConflict('lala', file_id='lala-id')
240
expected = conflicts.ContentsConflict('lala', file_id='lala-id')
222
241
self.assertEqual(list(tree.conflicts()), [expected])
223
242
file('lala.THIS', 'wb').write('lathis')
224
243
file('lala.OTHER', 'wb').write('laother')
225
244
# When "text conflict"s happen, stem, THIS and OTHER are text
226
expected = TextConflict('lala', file_id='lala-id')
245
expected = conflicts.TextConflict('lala', file_id='lala-id')
227
246
self.assertEqual(list(tree.conflicts()), [expected])
228
247
os.unlink('lala.OTHER')
229
248
os.mkdir('lala.OTHER')
230
expected = ContentsConflict('lala', file_id='lala-id')
249
expected = conflicts.ContentsConflict('lala', file_id='lala-id')
231
250
self.assertEqual(list(tree.conflicts()), [expected])
253
class InstrumentedTree(object):
254
"""A instrumented tree to check the needs_tree_write_lock decorator."""
259
def lock_tree_write(self):
260
self._locks.append('t')
262
@needs_tree_write_lock
263
def method_with_tree_write_lock(self, *args, **kwargs):
264
"""A lock_tree_write decorated method that returns its arguments."""
267
@needs_tree_write_lock
268
def method_that_raises(self):
269
"""This method causes an exception when called with parameters.
271
This allows the decorator code to be checked - it should still call
276
self._locks.append('u')
279
class TestInstrumentedTree(TestCase):
281
def test_needs_tree_write_lock(self):
282
"""@needs_tree_write_lock should be semantically transparent."""
283
tree = InstrumentedTree()
285
'method_with_tree_write_lock',
286
tree.method_with_tree_write_lock.__name__)
288
"A lock_tree_write decorated method that returns its arguments.",
289
tree.method_with_tree_write_lock.__doc__)
292
result = tree.method_with_tree_write_lock(1,2,3, a='b')
293
self.assertEqual((args, kwargs), result)
294
self.assertEqual(['t', 'u'], tree._locks)
295
self.assertRaises(TypeError, tree.method_that_raises, 'foo')
296
self.assertEqual(['t', 'u', 't', 'u'], tree._locks)
299
class TestRevert(TestCaseWithTransport):
301
def test_revert_conflicts_recursive(self):
302
this_tree = self.make_branch_and_tree('this-tree')
303
self.build_tree_contents([('this-tree/foo/',),
304
('this-tree/foo/bar', 'bar')])
305
this_tree.add(['foo', 'foo/bar'])
306
this_tree.commit('created foo/bar')
307
other_tree = this_tree.bzrdir.sprout('other-tree').open_workingtree()
308
self.build_tree_contents([('other-tree/foo/bar', 'baz')])
309
other_tree.commit('changed bar')
310
self.build_tree_contents([('this-tree/foo/bar', 'qux')])
311
this_tree.commit('changed qux')
312
this_tree.merge_from_branch(other_tree.branch)
313
self.assertEqual(1, len(this_tree.conflicts()))
314
this_tree.revert(['foo'])
315
self.assertEqual(0, len(this_tree.conflicts()))
318
class TestAutoResolve(TestCaseWithTransport):
320
def test_auto_resolve(self):
321
base = self.make_branch_and_tree('base')
322
self.build_tree_contents([('base/hello', 'Hello')])
323
base.add('hello', 'hello_id')
325
other = base.bzrdir.sprout('other').open_workingtree()
326
self.build_tree_contents([('other/hello', 'hELLO')])
327
other.commit('Case switch')
328
this = base.bzrdir.sprout('this').open_workingtree()
329
self.failUnlessExists('this/hello')
330
self.build_tree_contents([('this/hello', 'Hello World')])
331
this.commit('Add World')
332
this.merge_from_branch(other.branch)
333
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
336
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
338
self.build_tree_contents([('this/hello', '<<<<<<<')])
340
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
342
self.build_tree_contents([('this/hello', '=======')])
344
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
346
self.build_tree_contents([('this/hello', '\n>>>>>>>')])
347
remaining, resolved = this.auto_resolve()
348
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
350
self.assertEqual([], resolved)
351
self.build_tree_contents([('this/hello', 'hELLO wORLD')])
352
remaining, resolved = this.auto_resolve()
353
self.assertEqual([], this.conflicts())
354
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
356
self.failIfExists('this/hello.BASE')
358
def test_auto_resolve_dir(self):
359
tree = self.make_branch_and_tree('tree')
360
self.build_tree(['tree/hello/'])
361
tree.add('hello', 'hello-id')
362
file_conflict = conflicts.TextConflict('file', None, 'hello-id')
363
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
367
class TestFindTrees(TestCaseWithTransport):
369
def test_find_trees(self):
370
self.make_branch_and_tree('foo')
371
self.make_branch_and_tree('foo/bar')
372
# Sticking a tree inside a control dir is heinous, so let's skip it
373
self.make_branch_and_tree('foo/.bzr/baz')
374
self.make_branch('qux')
375
trees = workingtree.WorkingTree.find_trees('.')
376
self.assertEqual(2, len(list(trees)))