37
38
PathsNotVersionedError,
39
40
from bzrlib.inventory import Inventory
41
from bzrlib.mutabletree import MutableTree
40
42
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
41
43
from bzrlib.tests import (
57
59
class TestWorkingTree(TestCaseWithWorkingTree):
61
def requireBranchReference(self):
62
test_branch = self.make_branch('test-branch')
64
# if there is a working tree now, this is not supported.
65
test_branch.bzrdir.open_workingtree()
66
raise TestNotApplicable("only on trees that can be separate"
67
" from their branch.")
68
except (errors.NoWorkingTree, errors.NotLocalUrl):
59
71
def test_branch_builder(self):
60
72
# Just a smoke test that we get a branch at the specified relpath
61
73
builder = self.make_branch_builder('foobar')
62
br = branch.Branch.open('foobar')
74
br = branch.Branch.open(self.get_url('foobar'))
64
76
def test_list_files(self):
65
77
tree = self.make_branch_and_tree('.')
120
132
self.assertEqual(('filename', 'V', 'directory', 'file-id'),
135
def test_get_config_stack(self):
136
# Smoke test that all working trees succeed getting a config
137
wt = self.make_branch_and_tree('.')
138
conf = wt.get_config_stack()
139
self.assertIsInstance(conf, config.Stack)
123
141
def test_open_containing(self):
124
branch = self.make_branch_and_tree('.').branch
125
local_base = urlutils.local_path_from_url(branch.base)
142
local_wt = self.make_branch_and_tree('.')
143
local_url = local_wt.bzrdir.root_transport.base
144
local_base = urlutils.local_path_from_url(local_url)
127
147
# Empty opens '.'
128
148
wt, relpath = WorkingTree.open_containing()
161
181
def test_lock_locks_branch(self):
162
182
tree = self.make_branch_and_tree('.')
183
self.assertEqual(None, tree.branch.peek_lock_mode())
164
185
self.assertEqual('r', tree.branch.peek_lock_mode())
174
195
tree = self.make_branch_and_tree('.')
176
197
self.build_tree(['hello.txt'])
177
file('hello.txt', 'w').write('initial hello')
198
with file('hello.txt', 'w') as f: f.write('initial hello')
179
200
self.assertRaises(PathsNotVersionedError,
180
201
tree.revert, ['hello.txt'])
182
203
tree.commit('create initial hello.txt')
184
205
self.check_file_contents('hello.txt', 'initial hello')
185
file('hello.txt', 'w').write('new hello')
206
with file('hello.txt', 'w') as f: f.write('new hello')
186
207
self.check_file_contents('hello.txt', 'new hello')
188
209
# revert file modified since last revision
196
217
self.check_file_contents('hello.txt.~1~', 'new hello')
198
219
# backup files are numbered
199
file('hello.txt', 'w').write('new hello2')
220
with file('hello.txt', 'w') as f: f.write('new hello2')
200
221
tree.revert(['hello.txt'])
201
222
self.check_file_contents('hello.txt', 'initial hello')
202
223
self.check_file_contents('hello.txt.~1~', 'new hello')
205
226
def test_revert_missing(self):
206
227
# Revert a file that has been deleted since last commit
207
228
tree = self.make_branch_and_tree('.')
208
file('hello.txt', 'w').write('initial hello')
229
with file('hello.txt', 'w') as f: f.write('initial hello')
209
230
tree.add('hello.txt')
210
231
tree.commit('added hello.txt')
211
232
os.unlink('hello.txt')
217
238
tree = self.make_branch_and_tree('.')
218
239
self.build_tree(['hello.txt'])
219
240
tree.add('hello.txt')
220
self.assertEquals(list(tree.unknowns()),
241
self.assertEqual(list(tree.unknowns()),
223
244
def test_unknowns(self):
226
247
'hello.txt.~1~'])
227
248
self.build_tree_contents([('.bzrignore', '*.~*\n')])
228
249
tree.add('.bzrignore')
229
self.assertEquals(list(tree.unknowns()),
250
self.assertEqual(list(tree.unknowns()),
232
253
def test_initialize(self):
250
271
wt.commit('create initial state')
252
revid = b.revision_history()[0]
273
revid = b.last_revision()
253
274
self.log('first revision_id is {%s}' % revid)
255
276
tree = b.repository.revision_tree(revid)
312
333
cloned = cloned_dir.open_workingtree()
313
334
self.assertEqual(cloned.get_parent_ids(), wt.get_parent_ids())
336
def test_clone_empty(self):
337
wt = self.make_branch_and_tree('source')
338
cloned_dir = wt.bzrdir.clone('target', revision_id=_mod_revision.NULL_REVISION)
339
cloned = cloned_dir.open_workingtree()
340
self.assertEqual(cloned.get_parent_ids(), wt.get_parent_ids())
315
342
def test_last_revision(self):
316
343
wt = self.make_branch_and_tree('source')
317
344
self.assertEqual([], wt.get_parent_ids())
329
356
wt.set_last_revision('null:')
330
357
wt.commit('A', allow_pointless=True, rev_id='A')
331
358
self.assertEqual(['A'], wt.get_parent_ids())
332
# None is aways in the branch
359
# null: is aways in the branch
333
360
wt.set_last_revision('null:')
334
361
self.assertEqual([], wt.get_parent_ids())
335
362
# and now we can set it to 'A'
336
363
# because some formats mutate the branch to set it on the tree
337
364
# we need to alter the branch to let this pass.
339
self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
340
wt.branch.set_revision_history, ['A', 'B'])
341
except errors.NoSuchRevision, e:
342
self.assertEqual('B', e.revision)
365
if getattr(wt.branch, "_set_revision_history", None) is None:
343
366
raise TestSkipped("Branch format does not permit arbitrary"
368
wt.branch._set_revision_history(['A', 'B'])
345
369
wt.set_last_revision('A')
346
370
self.assertEqual(['A'], wt.get_parent_ids())
347
371
self.assertRaises(errors.ReservedId, wt.set_last_revision, 'A:')
355
379
# that formats where initialising a branch does not initialise a
356
380
# tree - and thus have separable entities - support skewing the
358
branch = self.make_branch('tree')
360
# if there is a working tree now, this is not supported.
361
branch.bzrdir.open_workingtree()
363
except errors.NoWorkingTree:
365
wt = branch.bzrdir.create_workingtree()
382
self.requireBranchReference()
383
wt = self.make_branch_and_tree('tree')
366
384
wt.commit('A', allow_pointless=True, rev_id='A')
367
385
wt.set_last_revision(None)
368
386
self.assertEqual([], wt.get_parent_ids())
446
464
self.assertEqual(['a'], made_tree.get_parent_ids())
466
def test_post_build_tree_hook(self):
468
def track_post_build_tree(tree):
469
calls.append(tree.last_revision())
470
source = self.make_branch_and_tree('source')
471
source.commit('a', rev_id='a', allow_pointless=True)
472
source.commit('b', rev_id='b', allow_pointless=True)
473
self.build_tree(['new/'])
474
made_control = self.bzrdir_format.initialize('new')
475
source.branch.repository.clone(made_control)
476
source.branch.clone(made_control)
477
MutableTree.hooks.install_named_hook("post_build_tree",
478
track_post_build_tree, "Test")
479
made_tree = self.workingtree_format.initialize(made_control,
481
self.assertEqual(['a'], calls)
448
483
def test_update_sets_last_revision(self):
449
484
# working tree formats from the meta-dir format and newer support
450
485
# setting the last revision on a tree independently of that on the
454
489
# that formats where initialising a branch does not initialise a
455
490
# tree - and thus have separable entities - support skewing the
457
main_branch = self.make_branch('tree')
459
# if there is a working tree now, this is not supported.
460
main_branch.bzrdir.open_workingtree()
462
except errors.NoWorkingTree:
464
wt = main_branch.bzrdir.create_workingtree()
492
self.requireBranchReference()
493
wt = self.make_branch_and_tree('tree')
465
494
# create an out of date working tree by making a checkout in this
467
496
self.build_tree(['checkout/', 'tree/file'])
468
497
checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
469
branch.BranchReferenceFormat().initialize(checkout,
470
target_branch=main_branch)
498
checkout.set_branch_reference(wt.branch)
471
499
old_tree = self.workingtree_format.initialize(checkout)
472
500
# now commit to 'tree'
522
550
# that formats where initialising a branch does not initialise a
523
551
# tree - and thus have separable entities - support skewing the
525
main_branch = self.make_branch('tree')
527
# if there is a working tree now, this is not supported.
528
main_branch.bzrdir.open_workingtree()
530
except errors.NoWorkingTree:
532
wt = main_branch.bzrdir.create_workingtree()
553
self.requireBranchReference()
554
wt = self.make_branch_and_tree('tree')
533
555
# create an out of date working tree by making a checkout in this
535
557
self.build_tree(['checkout/', 'tree/file'])
536
558
checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
537
branch.BranchReferenceFormat().initialize(checkout,
538
target_branch=main_branch)
559
checkout.set_branch_reference(wt.branch)
539
560
old_tree = self.workingtree_format.initialize(checkout)
540
561
# now commit to 'tree'
623
644
# which should have pivoted the local tip into a merge
624
645
self.assertEqual([master_tip, 'bar'], tree.get_parent_ids())
625
646
# and the local branch history should match the masters now.
626
self.assertEqual(master_tree.branch.revision_history(),
627
tree.branch.revision_history())
647
self.assertEqual(master_tree.branch.last_revision(),
648
tree.branch.last_revision())
629
650
def test_update_takes_revision_parameter(self):
630
651
wt = self.make_branch_and_tree('wt')
660
681
tree.add(['somefile'], ['file-id'])
661
682
tree.set_merge_modified(d)
662
683
mm = tree.merge_modified()
663
self.assertEquals(mm, d)
684
self.assertEqual(mm, d)
666
687
mm = tree.merge_modified()
667
self.assertEquals(mm, d)
688
self.assertEqual(mm, d)
669
690
def test_conflicts(self):
670
691
from bzrlib.tests.test_conflicts import example_conflicts
686
707
def make_merge_conflicts(self):
687
708
from bzrlib.merge import merge_inner
688
709
tree = self.make_branch_and_tree('mine')
689
file('mine/bloo', 'wb').write('one')
690
file('mine/blo', 'wb').write('on')
710
with file('mine/bloo', 'wb') as f: f.write('one')
711
with file('mine/blo', 'wb') as f: f.write('on')
691
712
tree.add(['bloo', 'blo'])
692
713
tree.commit("blah", allow_pointless=False)
693
714
base = tree.branch.repository.revision_tree(tree.last_revision())
694
bzrdir.BzrDir.open("mine").sprout("other")
695
file('other/bloo', 'wb').write('two')
715
controldir.ControlDir.open("mine").sprout("other")
716
with file('other/bloo', 'wb') as f: f.write('two')
696
717
othertree = WorkingTree.open('other')
697
718
othertree.commit('blah', allow_pointless=False)
698
file('mine/bloo', 'wb').write('three')
719
with file('mine/bloo', 'wb') as f: f.write('three')
699
720
tree.commit("blah", allow_pointless=False)
700
721
merge_inner(tree.branch, othertree, base, this_tree=tree)
954
975
tree = tree.bzrdir.open_workingtree()
955
976
self.assertFalse(tree.case_sensitive)
978
def test_supports_executable(self):
979
self.build_tree(['filename'])
980
tree = self.make_branch_and_tree('.')
982
self.assertIsInstance(tree._supports_executable(), bool)
983
if tree._supports_executable():
986
self.assertFalse(tree.is_executable(tree.path2id('filename')))
989
os.chmod('filename', 0755)
990
self.addCleanup(tree.lock_read().unlock)
991
self.assertTrue(tree.is_executable(tree.path2id('filename')))
993
self.addCleanup(tree.lock_read().unlock)
994
self.assertFalse(tree.is_executable(tree.path2id('filename')))
957
996
def test_all_file_ids_with_missing(self):
958
997
tree = self.make_branch_and_tree('tree')
959
998
tree.lock_write()
1161
1200
def test_set_in_branch(self):
1162
1201
wt = self.make_wt_with_worth_saving_limit()
1163
conf = config.BranchStack(wt.branch)
1202
conf = wt.get_config_stack()
1164
1203
conf.set('bzr.workingtree.worth_saving_limit', '20')
1165
1204
self.assertEqual(20, wt._worth_saving_limit())
1166
1205
ds = wt.current_dirstate()
1169
1208
def test_invalid(self):
1170
1209
wt = self.make_wt_with_worth_saving_limit()
1171
conf = config.BranchStack(wt.branch)
1210
conf = wt.get_config_stack()
1172
1211
conf.set('bzr.workingtree.worth_saving_limit', 'a')
1173
1212
# If the config entry is invalid, default to 10
1177
1216
self.overrideAttr(trace, 'warning', warning)
1178
1217
self.assertEqual(10, wt._worth_saving_limit())
1179
1218
self.assertLength(1, warnings)
1180
self.assertEquals('Value "a" is not valid for'
1219
self.assertEqual('Value "a" is not valid for'
1181
1220
' "bzr.workingtree.worth_saving_limit"',