19
19
from cStringIO import StringIO
24
23
from bzrlib import (
29
revision as _mod_revision,
34
from bzrlib.errors import (NotBranchError, NotVersionedError,
35
UnsupportedOperation, PathsNotVersionedError)
35
from bzrlib.errors import (
37
PathsNotVersionedError,
36
39
from bzrlib.inventory import Inventory
37
40
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
38
from bzrlib.tests import TestSkipped, TestNotApplicable
41
from bzrlib.tests import (
39
46
from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
40
from bzrlib.trace import mutter
41
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
42
WorkingTree, WorkingTree2)
47
from bzrlib.workingtree import (
43
54
from bzrlib.conflicts import ConflictList, TextConflict, ContentsConflict
46
57
class TestWorkingTree(TestCaseWithWorkingTree):
59
def test_branch_builder(self):
60
# Just a smoke test that we get a branch at the specified relpath
61
builder = self.make_branch_builder('foobar')
62
br = branch.Branch.open('foobar')
48
64
def test_list_files(self):
49
65
tree = self.make_branch_and_tree('.')
50
66
self.build_tree(['dir/', 'file'])
195
211
os.unlink('hello.txt')
196
212
tree.remove('hello.txt')
197
213
tree.revert(['hello.txt'])
198
self.failUnlessExists('hello.txt')
214
self.assertPathExists('hello.txt')
200
216
def test_versioned_files_not_unknown(self):
201
217
tree = self.make_branch_and_tree('.')
234
250
wt.commit('create initial state')
236
revid = b.revision_history()[0]
252
revid = b.last_revision()
237
253
self.log('first revision_id is {%s}' % revid)
239
inv = b.repository.get_inventory(revid)
240
self.log('contents of inventory: %r' % inv.entries())
255
tree = b.repository.revision_tree(revid)
256
self.log('contents of tree: %r' % list(tree.iter_entries_by_dir()))
242
self.check_inventory_shape(inv,
243
['dir/', 'dir/sub/', 'dir/sub/file'])
258
self.check_tree_shape(tree, ['dir/', 'dir/sub/', 'dir/sub/file'])
244
259
wt.rename_one('dir', 'newdir')
247
self.check_inventory_shape(wt.inventory,
262
self.check_tree_shape(wt,
248
263
['newdir/', 'newdir/sub/', 'newdir/sub/file'])
250
265
wt.rename_one('newdir/sub', 'newdir/newsub')
252
self.check_inventory_shape(wt.inventory,
253
['newdir/', 'newdir/newsub/',
267
self.check_tree_shape(wt, ['newdir/', 'newdir/newsub/',
254
268
'newdir/newsub/file'])
264
278
wt = self.make_branch_and_tree('.')
265
279
self.build_tree(['foo/',
267
self.assertRaises(NotVersionedError,
281
if not wt._format.supports_versioned_directories:
284
self.assertRaises(NotVersionedError,
271
288
def test_add_missing(self):
272
289
# adding a msising file -> NoSuchFile
295
312
cloned = cloned_dir.open_workingtree()
296
313
self.assertEqual(cloned.get_parent_ids(), wt.get_parent_ids())
315
def test_clone_empty(self):
316
wt = self.make_branch_and_tree('source')
317
cloned_dir = wt.bzrdir.clone('target', revision_id=_mod_revision.NULL_REVISION)
318
cloned = cloned_dir.open_workingtree()
319
self.assertEqual(cloned.get_parent_ids(), wt.get_parent_ids())
298
321
def test_last_revision(self):
299
322
wt = self.make_branch_and_tree('source')
300
323
self.assertEqual([], wt.get_parent_ids())
319
342
# because some formats mutate the branch to set it on the tree
320
343
# we need to alter the branch to let this pass.
322
wt.branch.set_revision_history(['A', 'B'])
345
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
346
wt.branch.set_revision_history, ['A', 'B'])
323
347
except errors.NoSuchRevision, e:
324
348
self.assertEqual('B', e.revision)
325
349
raise TestSkipped("Branch format does not permit arbitrary"
390
414
wt.set_parent_ids(['B'])
391
415
tree = wt.basis_tree()
393
self.failUnless(tree.has_filename('bar'))
417
self.assertTrue(tree.has_filename('bar'))
395
419
wt.set_parent_ids(['A'])
396
420
tree = wt.basis_tree()
398
self.failUnless(tree.has_filename('foo'))
422
self.assertTrue(tree.has_filename('foo'))
401
425
def test_clone_tree_revision(self):
456
480
wt.commit('A', rev_id='A')
457
481
# and update old_tree
458
482
self.assertEqual(0, old_tree.update())
459
self.failUnlessExists('checkout/file')
483
self.assertPathExists('checkout/file')
460
484
self.assertEqual(['A'], old_tree.get_parent_ids())
462
486
def test_update_sets_root_id(self):
477
501
wt.commit('A', rev_id='A')
478
502
# and update checkout
479
503
self.assertEqual(0, checkout.update())
480
self.failUnlessExists('checkout/file')
504
self.assertPathExists('checkout/file')
481
505
self.assertEqual(wt.get_root_id(), checkout.get_root_id())
482
506
self.assertNotEqual(None, wt.get_root_id())
560
584
self.assertFileEqual('a test\n', 'b1/a')
561
self.failUnlessExists('b1/b.~1~')
562
self.failIfExists('b1/c')
563
self.failIfExists('b1/a.~1~')
564
self.failUnlessExists('b1/d')
585
self.assertPathExists('b1/b.~1~')
586
self.assertPathDoesNotExist('b1/c')
587
self.assertPathDoesNotExist('b1/a.~1~')
588
self.assertPathExists('b1/d')
566
590
def test_update_updates_bound_branch_no_local_commits(self):
567
591
# doing an update in a tree updates the branch its bound to too.
605
629
# which should have pivoted the local tip into a merge
606
630
self.assertEqual([master_tip, 'bar'], tree.get_parent_ids())
607
631
# and the local branch history should match the masters now.
608
self.assertEqual(master_tree.branch.revision_history(),
609
tree.branch.revision_history())
632
self.assertEqual(master_tree.branch.last_revision(),
633
tree.branch.last_revision())
611
635
def test_update_takes_revision_parameter(self):
612
636
wt = self.make_branch_and_tree('wt')
626
650
# FIXME: This doesn't really test that it works; also this is not
627
651
# implementation-independent. mbp 20070226
628
652
tree = self.make_branch_and_tree('master')
653
if not isinstance(tree, InventoryWorkingTree):
654
raise TestNotApplicable("merge-hashes is specific to bzr "
629
656
tree._transport.put_bytes('merge-hashes', 'asdfasdf')
630
657
self.assertRaises(errors.MergeModifiedFormatError, tree.merge_modified)
730
757
def test_format_description(self):
731
758
tree = self.make_branch_and_tree('tree')
732
759
text = tree._format.get_format_description()
733
self.failUnless(len(text))
760
self.assertTrue(len(text))
735
762
def test_branch_attribute_is_not_settable(self):
736
763
# the branch attribute is an aspect of the working tree, not a
768
795
self.assertEqual([('', 'directory'), (u'\xe5', 'file')],
769
796
[(path, ie.kind) for path,ie in
770
tree.inventory.iter_entries()])
797
tree.iter_entries_by_dir()])
773
800
osutils.normalized_filename = orig
789
816
def test__write_inventory(self):
790
817
# The private interface _write_inventory is currently used by transform.
791
818
tree = self.make_branch_and_tree('.')
819
if not isinstance(tree, InventoryWorkingTree):
820
raise TestNotApplicable("_write_inventory does not exist on "
821
"non-inventory working trees")
792
822
# if we write write an inventory then do a walkdirs we should get back
793
823
# missing entries, and actual, and unknowns as appropriate.
794
824
self.build_tree(['present', 'unknown'])
916
946
case_sensitive = True
917
947
tree = self.make_branch_and_tree('test')
918
if tree.__class__ == WorkingTree2:
919
raise TestSkipped('WorkingTree2 is not supported')
920
948
self.assertEqual(case_sensitive, tree.case_sensitive)
949
if not isinstance(tree, InventoryWorkingTree):
950
raise TestNotApplicable("get_format_string is only available "
951
"on bzr working trees")
952
# now we cheat, and make a file that matches the case-sensitive name
953
t = tree.bzrdir.get_workingtree_transport(None)
955
content = tree._format.get_format_string()
956
except NotImplementedError:
957
# All-in-one formats didn't have a separate format string.
958
content = tree.bzrdir._format.get_format_string()
959
t.put_bytes(tree._format.case_sensitive_filename, content)
960
tree = tree.bzrdir.open_workingtree()
961
self.assertFalse(tree.case_sensitive)
922
963
def test_all_file_ids_with_missing(self):
923
964
tree = self.make_branch_and_tree('tree')
1054
1094
self.assertEqual(0, wt.update(revision='1'))
1055
1095
self.assertEqual('1', wt.last_revision())
1056
1096
self.assertEqual(tip, wt.branch.last_revision())
1057
self.failUnlessExists('checkout/file1')
1058
self.failIfExists('checkout/file4')
1059
self.failIfExists('checkout/file5')
1097
self.assertPathExists('checkout/file1')
1098
self.assertPathDoesNotExist('checkout/file4')
1099
self.assertPathDoesNotExist('checkout/file5')
1062
1102
class TestIllegalPaths(TestCaseWithWorkingTree):
1065
1105
if osutils.normalizes_filenames():
1066
1106
# You *can't* create an illegal filename on OSX.
1067
1107
raise tests.TestNotApplicable('OSX normalizes filenames')
1068
self.requireFeature(tests.UTF8Filesystem)
1108
self.requireFeature(features.UTF8Filesystem)
1069
1109
# We require a UTF8 filesystem, because otherwise we would need to get
1070
1110
# tricky to figure out how to create an illegal filename.
1071
1111
# \xb5 is an illegal path because it should be \xc2\xb5 for UTF-8
1104
1144
# above the control dir but we might need to relax that?
1105
1145
self.assertEqual(wt.control_url.find(wt.user_url), 0)
1106
1146
self.assertEqual(wt.control_url, wt.control_transport.base)
1149
class TestWorthSavingLimit(TestCaseWithWorkingTree):
1151
def make_wt_with_worth_saving_limit(self):
1152
wt = self.make_branch_and_tree('wt')
1153
if getattr(wt, '_worth_saving_limit', None) is None:
1154
raise tests.TestNotApplicable('no _worth_saving_limit for'
1157
self.addCleanup(wt.unlock)
1160
def test_not_set(self):
1161
# Default should be 10
1162
wt = self.make_wt_with_worth_saving_limit()
1163
self.assertEqual(10, wt._worth_saving_limit())
1164
ds = wt.current_dirstate()
1165
self.assertEqual(10, ds._worth_saving_limit)
1167
def test_set_in_branch(self):
1168
wt = self.make_wt_with_worth_saving_limit()
1169
conf = config.BranchStack(wt.branch)
1170
conf.set('bzr.workingtree.worth_saving_limit', '20')
1171
self.assertEqual(20, wt._worth_saving_limit())
1172
ds = wt.current_dirstate()
1173
self.assertEqual(10, ds._worth_saving_limit)
1175
def test_invalid(self):
1176
wt = self.make_wt_with_worth_saving_limit()
1177
conf = config.BranchStack(wt.branch)
1178
conf.set('bzr.workingtree.worth_saving_limit', 'a')
1179
# If the config entry is invalid, default to 10
1182
warnings.append(args[0] % args[1:])
1183
self.overrideAttr(trace, 'warning', warning)
1184
self.assertEqual(10, wt._worth_saving_limit())
1185
self.assertLength(1, warnings)
1186
self.assertEquals('Value "a" is not valid for'
1187
' "bzr.workingtree.worth_saving_limit"',
1191
class TestFormatAttributes(TestCaseWithWorkingTree):
1193
def test_versioned_directories(self):
1195
[self.workingtree_format.supports_versioned_directories],