71
61
class TestDefaultFormat(TestCaseWithTransport):
73
63
def test_get_set_default_format(self):
74
old_format = workingtree.format_registry.get_default()
76
self.assertTrue(isinstance(
77
old_format, workingtree_4.WorkingTreeFormat6))
78
workingtree.format_registry.set_default(SampleTreeFormat())
80
# the default branch format is used by the meta dir format
81
# which is not the default bzrdir format at this point
82
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
83
dir.create_repository()
85
result = dir.create_workingtree()
86
self.assertEqual(result, 'A tree')
88
workingtree.format_registry.set_default(old_format)
89
self.assertEqual(old_format, workingtree.format_registry.get_default())
91
def test_from_string(self):
92
self.assertIsInstance(
93
SampleTreeFormat.from_string(b"Sample tree format."),
96
AssertionError, SampleTreeFormat.from_string,
97
b"Different format string.")
99
def test_get_set_default_format_by_key(self):
100
old_format = workingtree.format_registry.get_default()
102
format = SampleTreeFormat()
103
workingtree.format_registry.register(format)
104
self.addCleanup(workingtree.format_registry.remove, format)
105
self.assertTrue(isinstance(
106
old_format, workingtree_4.WorkingTreeFormat6))
107
workingtree.format_registry.set_default_key(format.get_format_string())
109
# the default branch format is used by the meta dir format
110
# which is not the default bzrdir format at this point
111
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
112
dir.create_repository()
114
result = dir.create_workingtree()
115
self.assertEqual(result, 'A tree')
117
workingtree.format_registry.set_default_key(
118
old_format.get_format_string())
119
self.assertEqual(old_format, workingtree.format_registry.get_default())
122
tree = self.make_branch_and_tree('.')
123
open_direct = workingtree.WorkingTree.open('.')
124
self.assertEqual(tree.basedir, open_direct.basedir)
125
open_no_args = workingtree.WorkingTree.open()
126
self.assertEqual(tree.basedir, open_no_args.basedir)
128
def test_open_containing(self):
129
tree = self.make_branch_and_tree('.')
130
open_direct, relpath = workingtree.WorkingTree.open_containing('.')
131
self.assertEqual(tree.basedir, open_direct.basedir)
132
self.assertEqual('', relpath)
133
open_no_args, relpath = workingtree.WorkingTree.open_containing()
134
self.assertEqual(tree.basedir, open_no_args.basedir)
135
self.assertEqual('', relpath)
136
open_subdir, relpath = workingtree.WorkingTree.open_containing(
138
self.assertEqual(tree.basedir, open_subdir.basedir)
139
self.assertEqual('subdir', relpath)
142
class SampleTreeFormat(bzrworkingtree.WorkingTreeFormatMetaDir):
64
old_format = workingtree.WorkingTreeFormat.get_default_format()
66
self.assertTrue(isinstance(old_format, workingtree.WorkingTreeFormat3))
67
workingtree.WorkingTreeFormat.set_default_format(SampleTreeFormat())
69
# the default branch format is used by the meta dir format
70
# which is not the default bzrdir format at this point
71
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
72
dir.create_repository()
74
result = dir.create_workingtree()
75
self.assertEqual(result, 'A tree')
77
workingtree.WorkingTreeFormat.set_default_format(old_format)
78
self.assertEqual(old_format, workingtree.WorkingTreeFormat.get_default_format())
81
class SampleTreeFormat(workingtree.WorkingTreeFormat):
143
82
"""A sample format
145
this format is initializable, unsupported to aid in testing the
84
this format is initializable, unsupported to aid in testing the
146
85
open and open_downlevel routines.
150
def get_format_string(cls):
88
def get_format_string(self):
151
89
"""See WorkingTreeFormat.get_format_string()."""
152
return b"Sample tree format."
90
return "Sample tree format."
154
def initialize(self, a_controldir, revision_id=None, from_branch=None,
155
accelerator_tree=None, hardlink=False):
92
def initialize(self, a_bzrdir, revision_id=None):
156
93
"""Sample branches cannot be created."""
157
t = a_controldir.get_workingtree_transport(self)
158
t.put_bytes('format', self.get_format_string())
94
t = a_bzrdir.get_workingtree_transport(self)
95
t.put('format', StringIO(self.get_format_string()))
161
98
def is_supported(self):
165
102
return "opened tree."
168
class SampleExtraTreeFormat(workingtree.WorkingTreeFormat):
169
"""A sample format that does not support use in a metadir.
173
def get_format_string(self):
174
# Not usable in a metadir, so no format string
177
def initialize(self, a_controldir, revision_id=None, from_branch=None,
178
accelerator_tree=None, hardlink=False):
179
raise NotImplementedError(self.initialize)
181
def is_supported(self):
184
def open(self, transport, _found=False):
185
raise NotImplementedError(self.open)
188
105
class TestWorkingTreeFormat(TestCaseWithTransport):
189
106
"""Tests for the WorkingTreeFormat facility."""
191
def test_find_format_string(self):
192
# is the right format object found for a working tree?
193
branch = self.make_branch('branch')
195
errors.NoWorkingTree,
196
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string,
198
transport = branch.controldir.get_workingtree_transport(None)
200
transport.put_bytes("format", b"some format name")
201
# The format does not have to be known by Bazaar,
202
# find_format_string just retrieves the name
205
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string(
208
108
def test_find_format(self):
209
109
# is the right format object found for a working tree?
210
110
# create a branch with a few known format objects.
211
111
self.build_tree(["foo/", "bar/"])
213
112
def check_format(format, url):
214
dir = format._matchingcontroldir.initialize(url)
113
dir = format._matchingbzrdir.initialize(url)
215
114
dir.create_repository()
216
115
dir.create_branch()
217
116
format.initialize(dir)
218
found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(
220
self.assertIsInstance(found_format, format.__class__)
221
check_format(workingtree_3.WorkingTreeFormat3(), "bar")
117
t = get_transport(url)
118
found_format = workingtree.WorkingTreeFormat.find_format(dir)
119
self.failUnless(isinstance(found_format, format.__class__))
120
check_format(workingtree.WorkingTreeFormat3(), "bar")
223
122
def test_find_format_no_tree(self):
224
123
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
225
124
self.assertRaises(errors.NoWorkingTree,
226
bzrworkingtree.WorkingTreeFormatMetaDir.find_format,
125
workingtree.WorkingTreeFormat.find_format,
229
128
def test_find_format_unknown_format(self):
232
131
dir.create_branch()
233
132
SampleTreeFormat().initialize(dir)
234
133
self.assertRaises(errors.UnknownFormatError,
235
bzrworkingtree.WorkingTreeFormatMetaDir.find_format,
134
workingtree.WorkingTreeFormat.find_format,
238
def test_find_format_with_features(self):
239
tree = self.make_branch_and_tree('.', format='2a')
240
tree.update_feature_flags({b"name": b"necessity"})
241
found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(
243
self.assertIsInstance(found_format, workingtree.WorkingTreeFormat)
244
self.assertEqual(found_format.features.get(b"name"), b"necessity")
246
bzrdir.MissingFeature, found_format.check_support_status, True)
248
bzrworkingtree.WorkingTreeFormatMetaDir.unregister_feature,
250
bzrworkingtree.WorkingTreeFormatMetaDir.register_feature(b"name")
251
found_format.check_support_status(True)
254
class TestWorkingTreeIterEntriesByDir_wSubtrees(TestCaseWithTransport):
256
def make_simple_tree(self):
257
tree = self.make_branch_and_tree('tree', format='development-subtree')
258
self.build_tree(['tree/a/', 'tree/a/b/', 'tree/a/b/c'])
259
tree.set_root_id(b'root-id')
260
tree.add(['a', 'a/b', 'a/b/c'], [b'a-id', b'b-id', b'c-id'])
261
tree.commit('initial')
264
def test_just_directory(self):
265
tree = self.make_simple_tree()
266
self.assertEqual([('directory', b'root-id'),
267
('directory', b'a-id'),
268
('directory', b'b-id'),
270
[(ie.kind, ie.file_id)
271
for path, ie in tree.iter_entries_by_dir()])
272
self.make_branch_and_tree('tree/a/b')
273
self.assertEqual([('tree-reference', b'b-id')],
274
[(ie.kind, ie.file_id)
275
for path, ie in tree.iter_entries_by_dir(
276
specific_files=['a/b'])])
278
def test_direct_subtree(self):
279
tree = self.make_simple_tree()
280
self.make_branch_and_tree('tree/a/b')
281
self.assertEqual([('directory', b'root-id'),
282
('directory', b'a-id'),
283
('tree-reference', b'b-id')],
284
[(ie.kind, ie.file_id)
285
for path, ie in tree.iter_entries_by_dir()])
287
def test_indirect_subtree(self):
288
tree = self.make_simple_tree()
289
self.make_branch_and_tree('tree/a')
290
self.assertEqual([('directory', b'root-id'),
291
('tree-reference', b'a-id')],
292
[(ie.kind, ie.file_id)
293
for path, ie in tree.iter_entries_by_dir()])
296
class TestWorkingTreeFormatRegistry(TestCase):
299
super(TestWorkingTreeFormatRegistry, self).setUp()
300
self.registry = workingtree.WorkingTreeFormatRegistry()
302
137
def test_register_unregister_format(self):
303
138
format = SampleTreeFormat()
304
self.registry.register(format)
305
self.assertEqual(format, self.registry.get(b"Sample tree format."))
306
self.registry.remove(format)
307
self.assertRaises(KeyError, self.registry.get, b"Sample tree format.")
309
def test_get_all(self):
310
format = SampleTreeFormat()
311
self.assertEqual([], self.registry._get_all())
312
self.registry.register(format)
313
self.assertEqual([format], self.registry._get_all())
315
def test_register_extra(self):
316
format = SampleExtraTreeFormat()
317
self.assertEqual([], self.registry._get_all())
318
self.registry.register_extra(format)
319
self.assertEqual([format], self.registry._get_all())
321
def test_register_extra_lazy(self):
322
self.assertEqual([], self.registry._get_all())
323
self.registry.register_extra_lazy("breezy.tests.test_workingtree",
324
"SampleExtraTreeFormat")
325
formats = self.registry._get_all()
326
self.assertEqual(1, len(formats))
327
self.assertIsInstance(formats[0], SampleExtraTreeFormat)
140
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
141
dir.create_repository()
144
format.initialize(dir)
145
# register a format for it.
146
workingtree.WorkingTreeFormat.register_format(format)
147
# which branch.Open will refuse (not supported)
148
self.assertRaises(errors.UnsupportedFormatError, workingtree.WorkingTree.open, '.')
149
# but open_downlevel will work
150
self.assertEqual(format.open(dir), workingtree.WorkingTree.open_downlevel('.'))
151
# unregister the format
152
workingtree.WorkingTreeFormat.unregister_format(format)
330
155
class TestWorkingTreeFormat3(TestCaseWithTransport):
342
167
# stat-cache = ??
343
168
# no inventory.basis yet
344
169
t = control.get_workingtree_transport(None)
345
self.assertEqualDiff(b'Bazaar-NG Working Tree format 3',
170
self.assertEqualDiff('Bazaar-NG Working Tree format 3',
346
171
t.get('format').read())
347
self.assertEqualDiff(t.get('inventory').read(),
348
b'<inventory format="5">\n'
351
self.assertEqualDiff(b'### bzr hashcache v5\n',
172
self.assertEqualDiff('<inventory format="5">\n'
174
t.get('inventory').read())
175
self.assertEqualDiff('### bzr hashcache v5\n',
352
176
t.get('stat-cache').read())
353
177
self.assertFalse(t.has('inventory.basis'))
354
178
# no last-revision file means 'None' or 'NULLREVISION'
355
179
self.assertFalse(t.has('last-revision'))
356
# TODO RBC 20060210 do a commit, check the inventory.basis is created
180
# TODO RBC 20060210 do a commit, check the inventory.basis is created
357
181
# correctly and last-revision file becomes present.
359
183
def test_uses_lockdir(self):
360
184
"""WorkingTreeFormat3 uses its own LockDir:
362
186
- lock is a directory
363
187
- when the WorkingTree is locked, LockDir can see that
365
189
t = self.get_transport()
366
190
url = self.get_url()
367
191
dir = bzrdir.BzrDirMetaFormat1().initialize(url)
368
dir.create_repository()
192
repo = dir.create_repository()
193
branch = dir.create_branch()
371
tree = workingtree_3.WorkingTreeFormat3().initialize(dir)
195
tree = workingtree.WorkingTreeFormat3().initialize(dir)
372
196
except errors.NotLocalUrl:
373
197
raise TestSkipped('Not a local URL')
374
198
self.assertIsDirectory('.bzr', t)
375
199
self.assertIsDirectory('.bzr/checkout', t)
376
200
self.assertIsDirectory('.bzr/checkout/lock', t)
377
201
our_lock = LockDir(t, '.bzr/checkout/lock')
378
self.assertEqual(our_lock.peek(), None)
379
with tree.lock_write():
380
self.assertTrue(our_lock.peek())
381
self.assertEqual(our_lock.peek(), None)
383
def test_missing_pending_merges(self):
384
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
385
control.create_repository()
386
control.create_branch()
387
tree = workingtree_3.WorkingTreeFormat3().initialize(control)
388
tree._transport.delete("pending-merges")
389
self.assertEqual([], tree.get_parent_ids())
392
class TestRevert(TestCaseWithTransport):
394
def test_revert_conflicts_recursive(self):
395
this_tree = self.make_branch_and_tree('this-tree')
396
self.build_tree_contents([('this-tree/foo/',),
397
('this-tree/foo/bar', b'bar')])
398
this_tree.add(['foo', 'foo/bar'])
399
this_tree.commit('created foo/bar')
400
other_tree = this_tree.controldir.sprout(
401
'other-tree').open_workingtree()
402
self.build_tree_contents([('other-tree/foo/bar', b'baz')])
403
other_tree.commit('changed bar')
404
self.build_tree_contents([('this-tree/foo/bar', b'qux')])
405
this_tree.commit('changed qux')
406
this_tree.merge_from_branch(other_tree.branch)
407
self.assertEqual(1, len(this_tree.conflicts()))
408
this_tree.revert(['foo'])
409
self.assertEqual(0, len(this_tree.conflicts()))
412
class TestAutoResolve(TestCaseWithTransport):
414
def _auto_resolve(self, tree):
415
"""Call auto_resolve on tree expecting deprecation"""
416
return self.applyDeprecated(
417
symbol_versioning.deprecated_in((3, 0, 1)),
420
def test_auto_resolve(self):
421
base = self.make_branch_and_tree('base')
422
self.build_tree_contents([('base/hello', b'Hello')])
423
base.add('hello', b'hello_id')
425
other = base.controldir.sprout('other').open_workingtree()
426
self.build_tree_contents([('other/hello', b'hELLO')])
427
other.commit('Case switch')
428
this = base.controldir.sprout('this').open_workingtree()
429
self.assertPathExists('this/hello')
430
self.build_tree_contents([('this/hello', b'Hello World')])
431
this.commit('Add World')
432
this.merge_from_branch(other.branch)
433
self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
435
self._auto_resolve(this)
436
self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
438
self.build_tree_contents([('this/hello', '<<<<<<<')])
439
self._auto_resolve(this)
440
self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
442
self.build_tree_contents([('this/hello', '=======')])
443
self._auto_resolve(this)
444
self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
446
self.build_tree_contents([('this/hello', '\n>>>>>>>')])
447
remaining, resolved = self._auto_resolve(this)
448
self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
450
self.assertEqual([], resolved)
451
self.build_tree_contents([('this/hello', b'hELLO wORLD')])
452
remaining, resolved = self._auto_resolve(this)
453
self.assertEqual([], this.conflicts())
454
self.assertEqual([conflicts.TextConflict('hello', b'hello_id')],
456
self.assertPathDoesNotExist('this/hello.BASE')
458
def test_unsupported_symlink_auto_resolve(self):
459
self.requireFeature(SymlinkFeature)
460
base = self.make_branch_and_tree('base')
461
self.build_tree_contents([('base/hello', 'Hello')])
462
base.add('hello', b'hello_id')
463
base.commit('commit 0')
464
other = base.controldir.sprout('other').open_workingtree()
465
self.build_tree_contents([('other/hello', 'Hello')])
466
os.symlink('other/hello', 'other/foo')
467
other.add('foo', b'foo_id')
468
other.commit('commit symlink')
469
this = base.controldir.sprout('this').open_workingtree()
470
self.assertPathExists('this/hello')
471
self.build_tree_contents([('this/hello', 'Hello')])
472
this.commit('commit 2')
474
trace.push_log_file(log)
475
os_symlink = getattr(os, 'symlink', None)
478
this.merge_from_branch(other.branch)
481
os.symlink = os_symlink
482
self.assertContainsRe(
484
b'Unable to create symlink "foo" on this filesystem')
486
def test_auto_resolve_dir(self):
487
tree = self.make_branch_and_tree('tree')
488
self.build_tree(['tree/hello/'])
489
tree.add('hello', b'hello-id')
490
file_conflict = conflicts.TextConflict('hello', b'hello-id')
491
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
492
remaining, resolved = self._auto_resolve(tree)
495
conflicts.ConflictList([conflicts.TextConflict(u'hello', 'hello-id')]))
496
self.assertEqual(resolved, [])
498
def test_auto_resolve_missing(self):
499
tree = self.make_branch_and_tree('tree')
500
file_conflict = conflicts.TextConflict('hello', b'hello-id')
501
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
502
remaining, resolved = self._auto_resolve(tree)
503
self.assertEqual(remaining, [])
506
conflicts.ConflictList([conflicts.TextConflict(u'hello', 'hello-id')]))
509
class TestStoredUncommitted(TestCaseWithTransport):
511
def store_uncommitted(self):
512
tree = self.make_branch_and_tree('tree')
513
tree.commit('get root in there')
514
self.build_tree_contents([('tree/file', b'content')])
515
tree.add('file', b'file-id')
516
tree.store_uncommitted()
519
def test_store_uncommitted(self):
520
self.store_uncommitted()
521
self.assertPathDoesNotExist('tree/file')
523
def test_store_uncommitted_no_change(self):
524
tree = self.make_branch_and_tree('tree')
525
tree.commit('get root in there')
526
tree.store_uncommitted()
527
self.assertIs(None, tree.branch.get_unshelver(tree))
529
def test_restore_uncommitted(self):
530
with write_locked(self.store_uncommitted()) as tree:
531
tree.restore_uncommitted()
532
self.assertPathExists('tree/file')
533
self.assertIs(None, tree.branch.get_unshelver(tree))
535
def test_restore_uncommitted_none(self):
536
tree = self.make_branch_and_tree('tree')
537
tree.restore_uncommitted()
202
self.assertEquals(our_lock.peek(), None)
204
self.assertTrue(our_lock.peek())
206
self.assertEquals(our_lock.peek(), None)
209
class TestFormat2WorkingTree(TestCaseWithTransport):
210
"""Tests that are specific to format 2 trees."""
212
def create_format2_tree(self, url):
213
return self.make_branch_and_tree(
214
url, format=bzrlib.bzrdir.BzrDirFormat6())
216
def test_conflicts(self):
217
# test backwards compatability
218
tree = self.create_format2_tree('.')
219
self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
221
file('lala.BASE', 'wb').write('labase')
222
expected = ContentsConflict('lala')
223
self.assertEqual(list(tree.conflicts()), [expected])
224
file('lala', 'wb').write('la')
225
tree.add('lala', 'lala-id')
226
expected = ContentsConflict('lala', file_id='lala-id')
227
self.assertEqual(list(tree.conflicts()), [expected])
228
file('lala.THIS', 'wb').write('lathis')
229
file('lala.OTHER', 'wb').write('laother')
230
# When "text conflict"s happen, stem, THIS and OTHER are text
231
expected = TextConflict('lala', file_id='lala-id')
232
self.assertEqual(list(tree.conflicts()), [expected])
233
os.unlink('lala.OTHER')
234
os.mkdir('lala.OTHER')
235
expected = ContentsConflict('lala', file_id='lala-id')
236
self.assertEqual(list(tree.conflicts()), [expected])