~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/per_workingtree/test_workingtree.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006-2012, 2016 Canonical Ltd
2
2
# Authors:  Robert Collins <robert.collins@canonical.com>
3
3
#           and others
4
4
#
22
22
 
23
23
from bzrlib import (
24
24
    branch,
25
 
    branchbuilder,
26
25
    bzrdir,
27
26
    config,
 
27
    controldir,
28
28
    errors,
29
29
    osutils,
 
30
    revision as _mod_revision,
30
31
    symbol_versioning,
31
32
    tests,
32
33
    trace,
37
38
    PathsNotVersionedError,
38
39
    )
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 (
42
44
    features,
56
58
 
57
59
class TestWorkingTree(TestCaseWithWorkingTree):
58
60
 
 
61
    def requireBranchReference(self):
 
62
        test_branch = self.make_branch('test-branch')
 
63
        try:
 
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):
 
69
            pass
 
70
 
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'))
63
75
 
64
76
    def test_list_files(self):
65
77
        tree = self.make_branch_and_tree('.')
120
132
        self.assertEqual(('filename', 'V', 'directory', 'file-id'),
121
133
                         result[0][:4])
122
134
 
 
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)
 
140
 
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)
 
145
        del local_wt
126
146
 
127
147
        # Empty opens '.'
128
148
        wt, relpath = WorkingTree.open_containing()
160
180
 
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())
163
184
        tree.lock_read()
164
185
        self.assertEqual('r', tree.branch.peek_lock_mode())
165
186
        tree.unlock()
174
195
        tree = self.make_branch_and_tree('.')
175
196
 
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')
178
199
 
179
200
        self.assertRaises(PathsNotVersionedError,
180
201
                          tree.revert, ['hello.txt'])
182
203
        tree.commit('create initial hello.txt')
183
204
 
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')
187
208
 
188
209
        # revert file modified since last revision
196
217
        self.check_file_contents('hello.txt.~1~', 'new hello')
197
218
 
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()),
221
242
                          [])
222
243
 
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()),
230
251
                          ['hello.txt'])
231
252
 
232
253
    def test_initialize(self):
249
270
 
250
271
        wt.commit('create initial state')
251
272
 
252
 
        revid = b.revision_history()[0]
 
273
        revid = b.last_revision()
253
274
        self.log('first revision_id is {%s}' % revid)
254
275
 
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())
314
335
 
 
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())
 
341
 
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.
338
 
        try:
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"
344
367
                              " history")
 
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
357
381
        # two things.
358
 
        branch = self.make_branch('tree')
359
 
        try:
360
 
            # if there is a working tree now, this is not supported.
361
 
            branch.bzrdir.open_workingtree()
362
 
            return
363
 
        except errors.NoWorkingTree:
364
 
            pass
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())
445
463
            revision_id='a')
446
464
        self.assertEqual(['a'], made_tree.get_parent_ids())
447
465
 
 
466
    def test_post_build_tree_hook(self):
 
467
        calls = []
 
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,
 
480
            revision_id='a')
 
481
        self.assertEqual(['a'], calls)
 
482
 
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
456
491
        # two things.
457
 
        main_branch = self.make_branch('tree')
458
 
        try:
459
 
            # if there is a working tree now, this is not supported.
460
 
            main_branch.bzrdir.open_workingtree()
461
 
            return
462
 
        except errors.NoWorkingTree:
463
 
            pass
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
466
495
        # current format
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'
473
501
        wt.add('file')
522
550
        # that formats where initialising a branch does not initialise a
523
551
        # tree - and thus have separable entities - support skewing the
524
552
        # two things.
525
 
        main_branch = self.make_branch('tree')
526
 
        try:
527
 
            # if there is a working tree now, this is not supported.
528
 
            main_branch.bzrdir.open_workingtree()
529
 
            return
530
 
        except errors.NoWorkingTree:
531
 
            pass
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
534
556
        # current format
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'
541
562
        wt.add('file')
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())
628
649
 
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)
664
685
        finally:
665
686
            tree.unlock()
666
687
        mm = tree.merge_modified()
667
 
        self.assertEquals(mm, d)
 
688
        self.assertEqual(mm, d)
668
689
 
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)
701
722
        return tree
954
975
        tree = tree.bzrdir.open_workingtree()
955
976
        self.assertFalse(tree.case_sensitive)
956
977
 
 
978
    def test_supports_executable(self):
 
979
        self.build_tree(['filename'])
 
980
        tree = self.make_branch_and_tree('.')
 
981
        tree.add('filename')
 
982
        self.assertIsInstance(tree._supports_executable(), bool)
 
983
        if tree._supports_executable():
 
984
            tree.lock_read()
 
985
            try:
 
986
                self.assertFalse(tree.is_executable(tree.path2id('filename')))
 
987
            finally:
 
988
                tree.unlock()
 
989
            os.chmod('filename', 0755)
 
990
            self.addCleanup(tree.lock_read().unlock)
 
991
            self.assertTrue(tree.is_executable(tree.path2id('filename')))
 
992
        else:
 
993
            self.addCleanup(tree.lock_read().unlock)
 
994
            self.assertFalse(tree.is_executable(tree.path2id('filename')))
 
995
 
957
996
    def test_all_file_ids_with_missing(self):
958
997
        tree = self.make_branch_and_tree('tree')
959
998
        tree.lock_write()
1160
1199
 
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()
1168
1207
 
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
1174
1213
        warnings = []
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"',
1182
1221
                          warnings[0])
1183
1222