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
26
29
from bzrlib.lockdir import LockDir
27
30
from bzrlib.mutabletree import needs_tree_write_lock
31
from bzrlib.symbol_versioning import zero_thirteen
28
32
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
33
from bzrlib.transport import get_transport
29
34
from bzrlib.workingtree import (
61
66
class TestDefaultFormat(TestCaseWithTransport):
63
68
def test_get_set_default_format(self):
64
old_format = workingtree.format_registry.get_default()
69
old_format = workingtree.WorkingTreeFormat.get_default_format()
66
71
self.assertTrue(isinstance(old_format, workingtree.WorkingTreeFormat3))
67
workingtree.format_registry.set_default(SampleTreeFormat())
72
workingtree.WorkingTreeFormat.set_default_format(SampleTreeFormat())
69
74
# the default branch format is used by the meta dir format
70
75
# which is not the default bzrdir format at this point
74
79
result = dir.create_workingtree()
75
80
self.assertEqual(result, 'A tree')
77
workingtree.format_registry.set_default(old_format)
78
self.assertEqual(old_format, workingtree.format_registry.get_default())
81
tree = self.make_branch_and_tree('.')
82
open_direct = workingtree.WorkingTree.open('.')
83
self.assertEqual(tree.basedir, open_direct.basedir)
84
open_no_args = workingtree.WorkingTree.open()
85
self.assertEqual(tree.basedir, open_no_args.basedir)
87
def test_open_containing(self):
88
tree = self.make_branch_and_tree('.')
89
open_direct, relpath = workingtree.WorkingTree.open_containing('.')
90
self.assertEqual(tree.basedir, open_direct.basedir)
91
self.assertEqual('', relpath)
92
open_no_args, relpath = workingtree.WorkingTree.open_containing()
93
self.assertEqual(tree.basedir, open_no_args.basedir)
94
self.assertEqual('', relpath)
95
open_subdir, relpath = workingtree.WorkingTree.open_containing('subdir')
96
self.assertEqual(tree.basedir, open_subdir.basedir)
97
self.assertEqual('subdir', relpath)
82
workingtree.WorkingTreeFormat.set_default_format(old_format)
83
self.assertEqual(old_format, workingtree.WorkingTreeFormat.get_default_format())
100
86
class SampleTreeFormat(workingtree.WorkingTreeFormat):
101
87
"""A sample format
103
this format is initializable, unsupported to aid in testing the
89
this format is initializable, unsupported to aid in testing the
104
90
open and open_downlevel routines.
108
94
"""See WorkingTreeFormat.get_format_string()."""
109
95
return "Sample tree format."
111
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
112
accelerator_tree=None, hardlink=False):
97
def initialize(self, a_bzrdir, revision_id=None):
113
98
"""Sample branches cannot be created."""
114
99
t = a_bzrdir.get_workingtree_transport(self)
115
100
t.put_bytes('format', self.get_format_string())
122
107
return "opened tree."
125
class SampleExtraTreeFormat(workingtree.WorkingTreeFormat):
126
"""A sample format that does not support use in a metadir.
130
def get_format_string(self):
131
# Not usable in a metadir, so no format string
134
def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
135
accelerator_tree=None, hardlink=False):
136
raise NotImplementedError(self.initialize)
138
def is_supported(self):
141
def open(self, transport, _found=False):
142
raise NotImplementedError(self.open)
145
110
class TestWorkingTreeFormat(TestCaseWithTransport):
146
111
"""Tests for the WorkingTreeFormat facility."""
154
119
dir.create_repository()
155
120
dir.create_branch()
156
121
format.initialize(dir)
157
t = transport.get_transport(url)
122
t = get_transport(url)
158
123
found_format = workingtree.WorkingTreeFormat.find_format(dir)
159
self.assertIsInstance(found_format, format.__class__)
124
self.failUnless(isinstance(found_format, format.__class__))
160
125
check_format(workingtree.WorkingTreeFormat3(), "bar")
162
127
def test_find_format_no_tree(self):
163
128
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
164
129
self.assertRaises(errors.NoWorkingTree,
184
149
format.initialize(dir)
185
150
# register a format for it.
186
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
187
workingtree.WorkingTreeFormat.register_format, format)
188
self.assertTrue(format in
189
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
190
workingtree.WorkingTreeFormat.get_formats))
151
workingtree.WorkingTreeFormat.register_format(format)
191
152
# which branch.Open will refuse (not supported)
192
153
self.assertRaises(errors.UnsupportedFormatError, workingtree.WorkingTree.open, '.')
193
154
# but open_downlevel will work
194
155
self.assertEqual(format.open(dir), workingtree.WorkingTree.open_downlevel('.'))
195
156
# unregister the format
196
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
197
workingtree.WorkingTreeFormat.unregister_format, format)
198
self.assertFalse(format in
199
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
200
workingtree.WorkingTreeFormat.get_formats))
203
class TestWorkingTreeFormatRegistry(TestCase):
206
super(TestWorkingTreeFormatRegistry, self).setUp()
207
self.registry = workingtree.WorkingTreeFormatRegistry()
209
def test_register_unregister_format(self):
210
format = SampleTreeFormat()
211
self.registry.register(format)
212
self.assertEquals(format, self.registry.get("Sample tree format."))
213
self.registry.remove(format)
214
self.assertRaises(KeyError, self.registry.get, "Sample tree format.")
216
def test_get_all(self):
217
format = SampleTreeFormat()
218
self.assertEquals([], self.registry._get_all())
219
self.registry.register(format)
220
self.assertEquals([format], self.registry._get_all())
222
def test_register_extra(self):
223
format = SampleExtraTreeFormat()
224
self.assertEquals([], self.registry._get_all())
225
self.registry.register_extra(format)
226
self.assertEquals([format], self.registry._get_all())
228
def test_register_extra_lazy(self):
229
self.assertEquals([], self.registry._get_all())
230
self.registry.register_extra_lazy("bzrlib.tests.test_workingtree",
231
"SampleExtraTreeFormat")
232
formats = self.registry._get_all()
233
self.assertEquals(1, len(formats))
234
self.assertIsInstance(formats[0], SampleExtraTreeFormat)
157
workingtree.WorkingTreeFormat.unregister_format(format)
237
160
class TestWorkingTreeFormat3(TestCaseWithTransport):
260
183
self.assertFalse(t.has('inventory.basis'))
261
184
# no last-revision file means 'None' or 'NULLREVISION'
262
185
self.assertFalse(t.has('last-revision'))
263
# TODO RBC 20060210 do a commit, check the inventory.basis is created
186
# TODO RBC 20060210 do a commit, check the inventory.basis is created
264
187
# correctly and last-revision file becomes present.
266
189
def test_uses_lockdir(self):
267
190
"""WorkingTreeFormat3 uses its own LockDir:
269
192
- lock is a directory
270
193
- when the WorkingTree is locked, LockDir can see that
293
216
control.create_repository()
294
217
control.create_branch()
295
218
tree = workingtree.WorkingTreeFormat3().initialize(control)
296
tree._transport.delete("pending-merges")
219
tree._control_files._transport.delete("pending-merges")
297
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-')
300
266
class InstrumentedTree(object):
301
267
"""A instrumented tree to check the needs_tree_write_lock decorator."""
343
309
self.assertEqual(['t', 'u', 't', 'u'], tree._locks)
346
class TestRevert(TestCaseWithTransport):
348
def test_revert_conflicts_recursive(self):
349
this_tree = self.make_branch_and_tree('this-tree')
350
self.build_tree_contents([('this-tree/foo/',),
351
('this-tree/foo/bar', 'bar')])
352
this_tree.add(['foo', 'foo/bar'])
353
this_tree.commit('created foo/bar')
354
other_tree = this_tree.bzrdir.sprout('other-tree').open_workingtree()
355
self.build_tree_contents([('other-tree/foo/bar', 'baz')])
356
other_tree.commit('changed bar')
357
self.build_tree_contents([('this-tree/foo/bar', 'qux')])
358
this_tree.commit('changed qux')
359
this_tree.merge_from_branch(other_tree.branch)
360
self.assertEqual(1, len(this_tree.conflicts()))
361
this_tree.revert(['foo'])
362
self.assertEqual(0, len(this_tree.conflicts()))
365
312
class TestAutoResolve(TestCaseWithTransport):
367
314
def test_auto_resolve(self):
373
320
self.build_tree_contents([('other/hello', 'hELLO')])
374
321
other.commit('Case switch')
375
322
this = base.bzrdir.sprout('this').open_workingtree()
376
self.assertPathExists('this/hello')
323
self.failUnlessExists('this/hello')
377
324
self.build_tree_contents([('this/hello', 'Hello World')])
378
325
this.commit('Add World')
379
326
this.merge_from_branch(other.branch)
380
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
327
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
381
328
this.conflicts())
382
329
this.auto_resolve()
383
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
330
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
384
331
this.conflicts())
385
332
self.build_tree_contents([('this/hello', '<<<<<<<')])
386
333
this.auto_resolve()
387
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
334
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
388
335
this.conflicts())
389
336
self.build_tree_contents([('this/hello', '=======')])
390
337
this.auto_resolve()
391
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
338
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
392
339
this.conflicts())
393
340
self.build_tree_contents([('this/hello', '\n>>>>>>>')])
394
341
remaining, resolved = this.auto_resolve()
395
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
342
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
396
343
this.conflicts())
397
344
self.assertEqual([], resolved)
398
345
self.build_tree_contents([('this/hello', 'hELLO wORLD')])
399
346
remaining, resolved = this.auto_resolve()
400
347
self.assertEqual([], this.conflicts())
401
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
348
self.assertEqual([conflicts.TextConflict('hello', None, 'hello_id')],
403
self.assertPathDoesNotExist('this/hello.BASE')
350
self.failIfExists('this/hello.BASE')
405
352
def test_auto_resolve_dir(self):
406
353
tree = self.make_branch_and_tree('tree')
407
354
self.build_tree(['tree/hello/'])
408
355
tree.add('hello', 'hello-id')
409
file_conflict = conflicts.TextConflict('file', 'hello-id')
356
file_conflict = conflicts.TextConflict('file', None, 'hello-id')
410
357
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
411
358
tree.auto_resolve()
414
class TestFindTrees(TestCaseWithTransport):
416
def test_find_trees(self):
417
self.make_branch_and_tree('foo')
418
self.make_branch_and_tree('foo/bar')
419
# Sticking a tree inside a control dir is heinous, so let's skip it
420
self.make_branch_and_tree('foo/.bzr/baz')
421
self.make_branch('qux')
422
trees = workingtree.WorkingTree.find_trees('.')
423
self.assertEqual(2, len(list(trees)))