18
18
from cStringIO import StringIO
27
22
from bzrlib.branch import Branch
23
import bzrlib.bzrdir as bzrdir
28
24
from bzrlib.bzrdir import BzrDir
29
from bzrlib.lockdir import LockDir
30
from bzrlib.mutabletree import needs_tree_write_lock
31
from bzrlib.symbol_versioning import zero_thirteen
32
from bzrlib.tests import TestCase, TestCaseWithTransport, TestSkipped
25
import bzrlib.errors as errors
26
from bzrlib.errors import NotBranchError, NotVersionedError
27
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
28
from bzrlib.tests import TestCaseWithTransport
29
from bzrlib.trace import mutter
33
30
from bzrlib.transport import get_transport
34
from bzrlib.workingtree import (
31
import bzrlib.workingtree as workingtree
32
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
42
35
class TestTreeDirectory(TestCaseWithTransport):
174
168
t = control.get_workingtree_transport(None)
175
169
self.assertEqualDiff('Bazaar-NG Working Tree format 3',
176
170
t.get('format').read())
177
# self.assertContainsRe(t.get('inventory').read(),
178
# '<inventory file_id="[^"]*" format="5">\n'
181
# WorkingTreeFormat3 doesn't default to creating a unique root id,
182
# because it is incompatible with older bzr versions
183
self.assertContainsRe(t.get('inventory').read(),
184
'<inventory format="5">\n'
171
self.assertEqualDiff('', t.get('lock').read())
172
self.assertEqualDiff('<inventory format="5">\n'
174
t.get('inventory').read())
187
175
self.assertEqualDiff('### bzr hashcache v5\n',
188
176
t.get('stat-cache').read())
189
177
self.assertFalse(t.has('inventory.basis'))
191
179
self.assertFalse(t.has('last-revision'))
192
180
# TODO RBC 20060210 do a commit, check the inventory.basis is created
193
181
# correctly and last-revision file becomes present.
195
def test_uses_lockdir(self):
196
"""WorkingTreeFormat3 uses its own LockDir:
198
- lock is a directory
199
- when the WorkingTree is locked, LockDir can see that
201
t = self.get_transport()
203
dir = bzrdir.BzrDirMetaFormat1().initialize(url)
204
repo = dir.create_repository()
205
branch = dir.create_branch()
207
tree = workingtree.WorkingTreeFormat3().initialize(dir)
208
except errors.NotLocalUrl:
209
raise TestSkipped('Not a local URL')
210
self.assertIsDirectory('.bzr', t)
211
self.assertIsDirectory('.bzr/checkout', t)
212
self.assertIsDirectory('.bzr/checkout/lock', t)
213
our_lock = LockDir(t, '.bzr/checkout/lock')
214
self.assertEquals(our_lock.peek(), None)
216
self.assertTrue(our_lock.peek())
218
self.assertEquals(our_lock.peek(), None)
220
def test_missing_pending_merges(self):
221
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
222
control.create_repository()
223
control.create_branch()
224
tree = workingtree.WorkingTreeFormat3().initialize(control)
225
tree._control_files._transport.delete("pending-merges")
226
self.assertEqual([], tree.get_parent_ids())
229
class TestFormat2WorkingTree(TestCaseWithTransport):
230
"""Tests that are specific to format 2 trees."""
232
def create_format2_tree(self, url):
233
return self.make_branch_and_tree(
234
url, format=bzrdir.BzrDirFormat6())
236
def test_conflicts(self):
237
# test backwards compatability
238
tree = self.create_format2_tree('.')
239
self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
241
file('lala.BASE', 'wb').write('labase')
242
expected = conflicts.ContentsConflict('lala')
243
self.assertEqual(list(tree.conflicts()), [expected])
244
file('lala', 'wb').write('la')
245
tree.add('lala', 'lala-id')
246
expected = conflicts.ContentsConflict('lala', file_id='lala-id')
247
self.assertEqual(list(tree.conflicts()), [expected])
248
file('lala.THIS', 'wb').write('lathis')
249
file('lala.OTHER', 'wb').write('laother')
250
# When "text conflict"s happen, stem, THIS and OTHER are text
251
expected = conflicts.TextConflict('lala', file_id='lala-id')
252
self.assertEqual(list(tree.conflicts()), [expected])
253
os.unlink('lala.OTHER')
254
os.mkdir('lala.OTHER')
255
expected = conflicts.ContentsConflict('lala', file_id='lala-id')
256
self.assertEqual(list(tree.conflicts()), [expected])
259
class TestNonFormatSpecificCode(TestCaseWithTransport):
260
"""This class contains tests of workingtree that are not format specific."""
262
def test_gen_file_id(self):
263
file_id = self.applyDeprecated(zero_thirteen, workingtree.gen_file_id,
265
self.assertStartsWith(file_id, 'filename-')
267
def test_gen_root_id(self):
268
file_id = self.applyDeprecated(zero_thirteen, workingtree.gen_root_id)
269
self.assertStartsWith(file_id, 'tree_root-')
272
class InstrumentedTree(object):
273
"""A instrumented tree to check the needs_tree_write_lock decorator."""
278
def lock_tree_write(self):
279
self._locks.append('t')
281
@needs_tree_write_lock
282
def method_with_tree_write_lock(self, *args, **kwargs):
283
"""A lock_tree_write decorated method that returns its arguments."""
286
@needs_tree_write_lock
287
def method_that_raises(self):
288
"""This method causes an exception when called with parameters.
290
This allows the decorator code to be checked - it should still call
295
self._locks.append('u')
298
class TestInstrumentedTree(TestCase):
300
def test_needs_tree_write_lock(self):
301
"""@needs_tree_write_lock should be semantically transparent."""
302
tree = InstrumentedTree()
304
'method_with_tree_write_lock',
305
tree.method_with_tree_write_lock.__name__)
307
"A lock_tree_write decorated method that returns its arguments.",
308
tree.method_with_tree_write_lock.__doc__)
311
result = tree.method_with_tree_write_lock(1,2,3, a='b')
312
self.assertEqual((args, kwargs), result)
313
self.assertEqual(['t', 'u'], tree._locks)
314
self.assertRaises(TypeError, tree.method_that_raises, 'foo')
315
self.assertEqual(['t', 'u', 't', 'u'], tree._locks)