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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from cStringIO import StringIO
22
from bzrlib.branch import Branch
23
import bzrlib.bzrdir as bzrdir
24
from bzrlib.bzrdir import BzrDir
25
from bzrlib.conflicts import *
26
import bzrlib.errors as errors
27
from bzrlib.errors import NotBranchError, NotVersionedError
28
from bzrlib.lockdir import LockDir
29
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
30
from bzrlib.tests import TestCaseWithTransport, TestSkipped
31
from bzrlib.trace import mutter
32
from bzrlib.transport import get_transport
33
import bzrlib.workingtree as workingtree
34
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27
workingtree as bzrworkingtree,
31
from ..lock import write_locked
32
from ..lockdir import LockDir
33
from . import TestCase, TestCaseWithTransport, TestSkipped
34
from ..workingtree import (
37
42
class TestTreeDirectory(TestCaseWithTransport):
61
66
class TestDefaultFormat(TestCaseWithTransport):
63
68
def test_get_set_default_format(self):
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):
69
old_format = workingtree.format_registry.get_default()
71
self.assertTrue(isinstance(old_format, workingtree_4.WorkingTreeFormat6))
72
workingtree.format_registry.set_default(SampleTreeFormat())
74
# the default branch format is used by the meta dir format
75
# which is not the default bzrdir format at this point
76
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
77
dir.create_repository()
79
result = dir.create_workingtree()
80
self.assertEqual(result, 'A tree')
82
workingtree.format_registry.set_default(old_format)
83
self.assertEqual(old_format, workingtree.format_registry.get_default())
85
def test_from_string(self):
86
self.assertIsInstance(
87
SampleTreeFormat.from_string("Sample tree format."),
89
self.assertRaises(AssertionError,
90
SampleTreeFormat.from_string, "Different format string.")
92
def test_get_set_default_format_by_key(self):
93
old_format = workingtree.format_registry.get_default()
95
format = SampleTreeFormat()
96
workingtree.format_registry.register(format)
97
self.addCleanup(workingtree.format_registry.remove, format)
98
self.assertTrue(isinstance(old_format, workingtree_4.WorkingTreeFormat6))
99
workingtree.format_registry.set_default_key(format.get_format_string())
101
# the default branch format is used by the meta dir format
102
# which is not the default bzrdir format at this point
103
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
104
dir.create_repository()
106
result = dir.create_workingtree()
107
self.assertEqual(result, 'A tree')
109
workingtree.format_registry.set_default_key(
110
old_format.get_format_string())
111
self.assertEqual(old_format, workingtree.format_registry.get_default())
114
tree = self.make_branch_and_tree('.')
115
open_direct = workingtree.WorkingTree.open('.')
116
self.assertEqual(tree.basedir, open_direct.basedir)
117
open_no_args = workingtree.WorkingTree.open()
118
self.assertEqual(tree.basedir, open_no_args.basedir)
120
def test_open_containing(self):
121
tree = self.make_branch_and_tree('.')
122
open_direct, relpath = workingtree.WorkingTree.open_containing('.')
123
self.assertEqual(tree.basedir, open_direct.basedir)
124
self.assertEqual('', relpath)
125
open_no_args, relpath = workingtree.WorkingTree.open_containing()
126
self.assertEqual(tree.basedir, open_no_args.basedir)
127
self.assertEqual('', relpath)
128
open_subdir, relpath = workingtree.WorkingTree.open_containing('subdir')
129
self.assertEqual(tree.basedir, open_subdir.basedir)
130
self.assertEqual('subdir', relpath)
133
class SampleTreeFormat(bzrworkingtree.WorkingTreeFormatMetaDir):
82
134
"""A sample format
84
this format is initializable, unsupported to aid in testing the
136
this format is initializable, unsupported to aid in testing the
85
137
open and open_downlevel routines.
88
def get_format_string(self):
141
def get_format_string(cls):
89
142
"""See WorkingTreeFormat.get_format_string()."""
90
143
return "Sample tree format."
92
def initialize(self, a_bzrdir, revision_id=None):
145
def initialize(self, a_controldir, revision_id=None, from_branch=None,
146
accelerator_tree=None, hardlink=False):
93
147
"""Sample branches cannot be created."""
94
t = a_bzrdir.get_workingtree_transport(self)
95
t.put('format', StringIO(self.get_format_string()))
148
t = a_controldir.get_workingtree_transport(self)
149
t.put_bytes('format', self.get_format_string())
98
152
def is_supported(self):
102
156
return "opened tree."
159
class SampleExtraTreeFormat(workingtree.WorkingTreeFormat):
160
"""A sample format that does not support use in a metadir.
164
def get_format_string(self):
165
# Not usable in a metadir, so no format string
168
def initialize(self, a_controldir, revision_id=None, from_branch=None,
169
accelerator_tree=None, hardlink=False):
170
raise NotImplementedError(self.initialize)
172
def is_supported(self):
175
def open(self, transport, _found=False):
176
raise NotImplementedError(self.open)
105
179
class TestWorkingTreeFormat(TestCaseWithTransport):
106
180
"""Tests for the WorkingTreeFormat facility."""
182
def test_find_format_string(self):
183
# is the right format object found for a working tree?
184
branch = self.make_branch('branch')
185
self.assertRaises(errors.NoWorkingTree,
186
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string, branch.controldir)
187
transport = branch.controldir.get_workingtree_transport(None)
189
transport.put_bytes("format", "some format name")
190
# The format does not have to be known by Bazaar,
191
# find_format_string just retrieves the name
192
self.assertEqual("some format name",
193
bzrworkingtree.WorkingTreeFormatMetaDir.find_format_string(branch.controldir))
108
195
def test_find_format(self):
109
196
# is the right format object found for a working tree?
110
197
# create a branch with a few known format objects.
111
198
self.build_tree(["foo/", "bar/"])
112
199
def check_format(format, url):
113
dir = format._matchingbzrdir.initialize(url)
200
dir = format._matchingcontroldir.initialize(url)
114
201
dir.create_repository()
115
202
dir.create_branch()
116
203
format.initialize(dir)
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")
204
t = transport.get_transport(url)
205
found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(dir)
206
self.assertIsInstance(found_format, format.__class__)
207
check_format(workingtree_3.WorkingTreeFormat3(), "bar")
122
209
def test_find_format_no_tree(self):
123
210
dir = bzrdir.BzrDirMetaFormat1().initialize('.')
124
211
self.assertRaises(errors.NoWorkingTree,
125
workingtree.WorkingTreeFormat.find_format,
212
bzrworkingtree.WorkingTreeFormatMetaDir.find_format,
128
215
def test_find_format_unknown_format(self):
131
218
dir.create_branch()
132
219
SampleTreeFormat().initialize(dir)
133
220
self.assertRaises(errors.UnknownFormatError,
134
workingtree.WorkingTreeFormat.find_format,
221
bzrworkingtree.WorkingTreeFormatMetaDir.find_format,
224
def test_find_format_with_features(self):
225
tree = self.make_branch_and_tree('.', format='2a')
226
tree.update_feature_flags({"name": "necessity"})
227
found_format = bzrworkingtree.WorkingTreeFormatMetaDir.find_format(
229
self.assertIsInstance(found_format, workingtree.WorkingTreeFormat)
230
self.assertEqual(found_format.features.get("name"), "necessity")
231
self.assertRaises(bzrdir.MissingFeature, found_format.check_support_status,
233
self.addCleanup(bzrworkingtree.WorkingTreeFormatMetaDir.unregister_feature,
235
bzrworkingtree.WorkingTreeFormatMetaDir.register_feature("name")
236
found_format.check_support_status(True)
239
class TestWorkingTreeIterEntriesByDir_wSubtrees(TestCaseWithTransport):
241
def make_simple_tree(self):
242
tree = self.make_branch_and_tree('tree', format='development-subtree')
243
self.build_tree(['tree/a/', 'tree/a/b/', 'tree/a/b/c'])
244
tree.set_root_id('root-id')
245
tree.add(['a', 'a/b', 'a/b/c'], ['a-id', 'b-id', 'c-id'])
246
tree.commit('initial')
249
def test_just_directory(self):
250
tree = self.make_simple_tree()
251
self.assertEqual([('directory', 'root-id'),
252
('directory', 'a-id'),
253
('directory', 'b-id'),
255
[(ie.kind, ie.file_id)
256
for path, ie in tree.iter_entries_by_dir()])
257
subtree = self.make_branch_and_tree('tree/a/b')
258
self.assertEqual([('tree-reference', 'b-id')],
259
[(ie.kind, ie.file_id)
260
for path, ie in tree.iter_entries_by_dir(['b-id'])])
262
def test_direct_subtree(self):
263
tree = self.make_simple_tree()
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')],
268
[(ie.kind, ie.file_id)
269
for path, ie in tree.iter_entries_by_dir()])
271
def test_indirect_subtree(self):
272
tree = self.make_simple_tree()
273
subtree = self.make_branch_and_tree('tree/a')
274
self.assertEqual([('directory', 'root-id'),
275
('tree-reference', 'a-id')],
276
[(ie.kind, ie.file_id)
277
for path, ie in tree.iter_entries_by_dir()])
280
class TestWorkingTreeFormatRegistry(TestCase):
283
super(TestWorkingTreeFormatRegistry, self).setUp()
284
self.registry = workingtree.WorkingTreeFormatRegistry()
137
286
def test_register_unregister_format(self):
138
287
format = SampleTreeFormat()
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)
288
self.registry.register(format)
289
self.assertEqual(format, self.registry.get("Sample tree format."))
290
self.registry.remove(format)
291
self.assertRaises(KeyError, self.registry.get, "Sample tree format.")
293
def test_get_all(self):
294
format = SampleTreeFormat()
295
self.assertEqual([], self.registry._get_all())
296
self.registry.register(format)
297
self.assertEqual([format], self.registry._get_all())
299
def test_register_extra(self):
300
format = SampleExtraTreeFormat()
301
self.assertEqual([], self.registry._get_all())
302
self.registry.register_extra(format)
303
self.assertEqual([format], self.registry._get_all())
305
def test_register_extra_lazy(self):
306
self.assertEqual([], self.registry._get_all())
307
self.registry.register_extra_lazy("breezy.tests.test_workingtree",
308
"SampleExtraTreeFormat")
309
formats = self.registry._get_all()
310
self.assertEqual(1, len(formats))
311
self.assertIsInstance(formats[0], SampleExtraTreeFormat)
155
314
class TestWorkingTreeFormat3(TestCaseWithTransport):
192
352
repo = dir.create_repository()
193
353
branch = dir.create_branch()
195
tree = workingtree.WorkingTreeFormat3().initialize(dir)
355
tree = workingtree_3.WorkingTreeFormat3().initialize(dir)
196
356
except errors.NotLocalUrl:
197
357
raise TestSkipped('Not a local URL')
198
358
self.assertIsDirectory('.bzr', t)
199
359
self.assertIsDirectory('.bzr/checkout', t)
200
360
self.assertIsDirectory('.bzr/checkout/lock', t)
201
361
our_lock = LockDir(t, '.bzr/checkout/lock')
202
self.assertEquals(our_lock.peek(), None)
362
self.assertEqual(our_lock.peek(), None)
203
363
tree.lock_write()
204
364
self.assertTrue(our_lock.peek())
206
self.assertEquals(our_lock.peek(), None)
208
def create_format2_tree(self, url):
209
return BzrDir.create_standalone_workingtree(url)
211
def test_conflicts_format2(self):
212
# test backwards compatability
213
tree = self.create_format2_tree('.')
214
self.assertRaises(errors.UnsupportedOperation, tree.set_conflicts,
216
file('lala.BASE', 'wb').write('labase')
217
expected = ContentsConflict('lala')
218
self.assertEqual(list(tree.conflicts()), [expected])
219
file('lala', 'wb').write('la')
220
tree.add('lala', 'lala-id')
221
expected = ContentsConflict('lala', file_id='lala-id')
222
self.assertEqual(list(tree.conflicts()), [expected])
223
file('lala.THIS', 'wb').write('lathis')
224
file('lala.OTHER', 'wb').write('laother')
225
# When "text conflict"s happen, stem, THIS and OTHER are text
226
expected = TextConflict('lala', file_id='lala-id')
227
self.assertEqual(list(tree.conflicts()), [expected])
228
os.unlink('lala.OTHER')
229
os.mkdir('lala.OTHER')
230
expected = ContentsConflict('lala', file_id='lala-id')
231
self.assertEqual(list(tree.conflicts()), [expected])
366
self.assertEqual(our_lock.peek(), None)
368
def test_missing_pending_merges(self):
369
control = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
370
control.create_repository()
371
control.create_branch()
372
tree = workingtree_3.WorkingTreeFormat3().initialize(control)
373
tree._transport.delete("pending-merges")
374
self.assertEqual([], tree.get_parent_ids())
377
class TestRevert(TestCaseWithTransport):
379
def test_revert_conflicts_recursive(self):
380
this_tree = self.make_branch_and_tree('this-tree')
381
self.build_tree_contents([('this-tree/foo/',),
382
('this-tree/foo/bar', 'bar')])
383
this_tree.add(['foo', 'foo/bar'])
384
this_tree.commit('created foo/bar')
385
other_tree = this_tree.controldir.sprout('other-tree').open_workingtree()
386
self.build_tree_contents([('other-tree/foo/bar', 'baz')])
387
other_tree.commit('changed bar')
388
self.build_tree_contents([('this-tree/foo/bar', 'qux')])
389
this_tree.commit('changed qux')
390
this_tree.merge_from_branch(other_tree.branch)
391
self.assertEqual(1, len(this_tree.conflicts()))
392
this_tree.revert(['foo'])
393
self.assertEqual(0, len(this_tree.conflicts()))
396
class TestAutoResolve(TestCaseWithTransport):
398
def test_auto_resolve(self):
399
base = self.make_branch_and_tree('base')
400
self.build_tree_contents([('base/hello', 'Hello')])
401
base.add('hello', 'hello_id')
403
other = base.controldir.sprout('other').open_workingtree()
404
self.build_tree_contents([('other/hello', 'hELLO')])
405
other.commit('Case switch')
406
this = base.controldir.sprout('this').open_workingtree()
407
self.assertPathExists('this/hello')
408
self.build_tree_contents([('this/hello', 'Hello World')])
409
this.commit('Add World')
410
this.merge_from_branch(other.branch)
411
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
414
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
416
self.build_tree_contents([('this/hello', '<<<<<<<')])
418
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
420
self.build_tree_contents([('this/hello', '=======')])
422
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
424
self.build_tree_contents([('this/hello', '\n>>>>>>>')])
425
remaining, resolved = this.auto_resolve()
426
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
428
self.assertEqual([], resolved)
429
self.build_tree_contents([('this/hello', 'hELLO wORLD')])
430
remaining, resolved = this.auto_resolve()
431
self.assertEqual([], this.conflicts())
432
self.assertEqual([conflicts.TextConflict('hello', 'hello_id')],
434
self.assertPathDoesNotExist('this/hello.BASE')
436
def test_auto_resolve_dir(self):
437
tree = self.make_branch_and_tree('tree')
438
self.build_tree(['tree/hello/'])
439
tree.add('hello', 'hello-id')
440
file_conflict = conflicts.TextConflict('file', 'hello-id')
441
tree.set_conflicts(conflicts.ConflictList([file_conflict]))
445
class TestFindTrees(TestCaseWithTransport):
447
def test_find_trees(self):
448
self.make_branch_and_tree('foo')
449
self.make_branch_and_tree('foo/bar')
450
# Sticking a tree inside a control dir is heinous, so let's skip it
451
self.make_branch_and_tree('foo/.bzr/baz')
452
self.make_branch('qux')
453
trees = workingtree.WorkingTree.find_trees('.')
454
self.assertEqual(2, len(list(trees)))
457
class TestStoredUncommitted(TestCaseWithTransport):
459
def store_uncommitted(self):
460
tree = self.make_branch_and_tree('tree')
461
tree.commit('get root in there')
462
self.build_tree_contents([('tree/file', 'content')])
463
tree.add('file', 'file-id')
464
tree.store_uncommitted()
467
def test_store_uncommitted(self):
468
self.store_uncommitted()
469
self.assertPathDoesNotExist('tree/file')
471
def test_store_uncommitted_no_change(self):
472
tree = self.make_branch_and_tree('tree')
473
tree.commit('get root in there')
474
tree.store_uncommitted()
475
self.assertIs(None, tree.branch.get_unshelver(tree))
477
def test_restore_uncommitted(self):
478
with write_locked(self.store_uncommitted()) as tree:
479
tree.restore_uncommitted()
480
self.assertPathExists('tree/file')
481
self.assertIs(None, tree.branch.get_unshelver(tree))
483
def test_restore_uncommitted_none(self):
484
tree = self.make_branch_and_tree('tree')
485
tree.restore_uncommitted()