~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_workingtree_4.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil, Patch Queue Manager, Jelmer Vernooij
  • Date: 2017-01-17 16:20:41 UTC
  • mfrom: (6619.1.2 trunk)
  • Revision ID: tarmac-20170117162041-oo62uk1qsmgc9j31
Merge 2.7 into trunk including fixes for bugs #1622039, #1644003, #1579093 and #1645017. [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007-2012, 2016 Canonical Ltd
2
2
# Authors:  Robert Collins <robert.collins@canonical.com>
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
29
29
    workingtree_4,
30
30
    )
31
31
from bzrlib.lockdir import LockDir
32
 
from bzrlib.tests import TestCaseWithTransport, TestSkipped
 
32
from bzrlib.tests import TestCaseWithTransport, TestSkipped, features
33
33
from bzrlib.tree import InterTree
34
34
 
35
35
 
57
57
        finally:
58
58
            state.unlock()
59
59
 
 
60
    def test_resets_ignores_on_last_unlock(self):
 
61
        # Only the last unlock call will actually reset the
 
62
        # ignores. (bug #785671)
 
63
        tree = self.make_workingtree()
 
64
        tree.lock_read()
 
65
        try:
 
66
            tree.lock_read()
 
67
            try:
 
68
                tree.is_ignored("foo")
 
69
            finally:
 
70
                tree.unlock()
 
71
            self.assertIsNot(None, tree._ignoreglobster)
 
72
        finally:
 
73
            tree.unlock()
 
74
        self.assertIs(None, tree._ignoreglobster)
 
75
 
60
76
    def test_uses_lockdir(self):
61
77
        """WorkingTreeFormat4 uses its own LockDir:
62
78
 
72
88
        self.assertIsDirectory('.bzr/checkout', t)
73
89
        self.assertIsDirectory('.bzr/checkout/lock', t)
74
90
        our_lock = LockDir(t, '.bzr/checkout/lock')
75
 
        self.assertEquals(our_lock.peek(), None)
 
91
        self.assertEqual(our_lock.peek(), None)
76
92
        tree.lock_write()
77
93
        self.assertTrue(our_lock.peek())
78
94
        tree.unlock()
79
 
        self.assertEquals(our_lock.peek(), None)
 
95
        self.assertEqual(our_lock.peek(), None)
80
96
 
81
97
    def make_workingtree(self, relpath=''):
82
98
        url = self.get_url(relpath)
174
190
        # it's given; any calls to forbidden methods will raise an
175
191
        # AssertionError
176
192
        repo = tree.branch.repository
177
 
        repo.get_revision = self.fail
178
 
        repo.get_inventory = self.fail
179
 
        repo._get_inventory_xml = self.fail
 
193
        self.overrideAttr(repo, "get_revision", self.fail)
 
194
        self.overrideAttr(repo, "get_inventory", self.fail)
 
195
        self.overrideAttr(repo, "_get_inventory_xml", self.fail)
180
196
        # try to set the parent trees.
181
197
        tree.set_parent_trees([(rev1, rev1_tree)])
182
198
 
196
212
        rev1 = subtree.commit('commit in subdir')
197
213
        rev1_tree = subtree.basis_tree()
198
214
        rev1_tree.lock_read()
199
 
        rev1_tree.inventory
 
215
        rev1_tree.root_inventory
200
216
        self.addCleanup(rev1_tree.unlock)
201
217
        rev2 = subtree.commit('second commit in subdir', allow_pointless=True)
202
218
        rev2_tree = subtree.basis_tree()
203
219
        rev2_tree.lock_read()
204
 
        rev2_tree.inventory
 
220
        rev2_tree.root_inventory
205
221
        self.addCleanup(rev2_tree.unlock)
206
222
 
207
223
        tree.branch.pull(subtree.branch)
214
230
        # answer 'get_parent_ids' for the revision tree- dirstate does not
215
231
        # cache the parents of a parent tree at this point.
216
232
        #repo.get_revision = self.fail
217
 
        repo.get_inventory = self.fail
218
 
        repo._get_inventory_xml = self.fail
 
233
        self.overrideAttr(repo, "get_inventory", self.fail)
 
234
        self.overrideAttr(repo, "_get_inventory_xml", self.fail)
219
235
        # set the parent trees.
220
236
        tree.set_parent_trees([(rev1, rev1_tree), (rev2, rev2_tree)])
221
237
        # read the first tree
258
274
        lock_and_call_current_dirstate(tree, 'lock_tree_write')
259
275
        self.assertRaises(errors.ObjectNotLocked, tree.current_dirstate)
260
276
 
 
277
    def test_set_parent_trees_uses_update_basis_by_delta(self):
 
278
        builder = self.make_branch_builder('source')
 
279
        builder.start_series()
 
280
        self.addCleanup(builder.finish_series)
 
281
        builder.build_snapshot('A', [], [
 
282
            ('add', ('', 'root-id', 'directory', None)),
 
283
            ('add', ('a', 'a-id', 'file', 'content\n'))])
 
284
        builder.build_snapshot('B', ['A'], [
 
285
            ('modify', ('a-id', 'new content\nfor a\n')),
 
286
            ('add', ('b', 'b-id', 'file', 'b-content\n'))])
 
287
        tree = self.make_workingtree('tree')
 
288
        source_branch = builder.get_branch()
 
289
        tree.branch.repository.fetch(source_branch.repository, 'B')
 
290
        tree.pull(source_branch, stop_revision='A')
 
291
        tree.lock_write()
 
292
        self.addCleanup(tree.unlock)
 
293
        state = tree.current_dirstate()
 
294
        called = []
 
295
        orig_update = state.update_basis_by_delta
 
296
        def log_update_basis_by_delta(delta, new_revid):
 
297
            called.append(new_revid)
 
298
            return orig_update(delta, new_revid)
 
299
        state.update_basis_by_delta = log_update_basis_by_delta
 
300
        basis = tree.basis_tree()
 
301
        self.assertEqual('a-id', basis.path2id('a'))
 
302
        self.assertEqual(None, basis.path2id('b'))
 
303
        def fail_set_parent_trees(trees, ghosts):
 
304
            raise AssertionError('dirstate.set_parent_trees() was called')
 
305
        state.set_parent_trees = fail_set_parent_trees
 
306
        repo = tree.branch.repository
 
307
        tree.pull(source_branch, stop_revision='B')
 
308
        self.assertEqual(['B'], called)
 
309
        basis = tree.basis_tree()
 
310
        self.assertEqual('a-id', basis.path2id('a'))
 
311
        self.assertEqual('b-id', basis.path2id('b'))
 
312
 
 
313
    def test_set_parent_trees_handles_missing_basis(self):
 
314
        builder = self.make_branch_builder('source')
 
315
        builder.start_series()
 
316
        self.addCleanup(builder.finish_series)
 
317
        builder.build_snapshot('A', [], [
 
318
            ('add', ('', 'root-id', 'directory', None)),
 
319
            ('add', ('a', 'a-id', 'file', 'content\n'))])
 
320
        builder.build_snapshot('B', ['A'], [
 
321
            ('modify', ('a-id', 'new content\nfor a\n')),
 
322
            ('add', ('b', 'b-id', 'file', 'b-content\n'))])
 
323
        builder.build_snapshot('C', ['A'], [
 
324
            ('add', ('c', 'c-id', 'file', 'c-content\n'))])
 
325
        b_c = self.make_branch('branch_with_c')
 
326
        b_c.pull(builder.get_branch(), stop_revision='C')
 
327
        b_b = self.make_branch('branch_with_b')
 
328
        b_b.pull(builder.get_branch(), stop_revision='B')
 
329
        # This is reproducing some of what 'switch' does, just to isolate the
 
330
        # set_parent_trees() step.
 
331
        wt = b_b.create_checkout('tree', lightweight=True)
 
332
        fmt = wt.bzrdir.find_branch_format()
 
333
        fmt.set_reference(wt.bzrdir, None, b_c)
 
334
        # Re-open with the new reference
 
335
        wt = wt.bzrdir.open_workingtree()
 
336
        wt.set_parent_trees([('C', b_c.repository.revision_tree('C'))])
 
337
        self.assertEqual(None, wt.basis_tree().path2id('b'))
 
338
 
261
339
    def test_new_dirstate_on_new_lock(self):
262
340
        # until we have detection for when a dirstate can be reused, we
263
341
        # want to reparse dirstate on every new lock.
438
516
 
439
517
    def test_unique_root_id_per_tree(self):
440
518
        # each time you initialize a new tree, it gets a different root id
441
 
        format_name = 'dirstate-with-subtree'
 
519
        format_name = 'development-subtree'
442
520
        tree1 = self.make_branch_and_tree('tree1',
443
521
            format=format_name)
444
522
        tree2 = self.make_branch_and_tree('tree2',
474
552
        tree = self.make_branch_and_tree('tag', format='dirstate-tags')
475
553
        self.assertEqual(inventory.ROOT_ID, tree.get_root_id())
476
554
        tree = self.make_branch_and_tree('subtree',
477
 
                                         format='dirstate-with-subtree')
 
555
                                         format='development-subtree')
478
556
        self.assertNotEqual(inventory.ROOT_ID, tree.get_root_id())
479
557
 
480
558
    def test_non_subtree_with_nested_trees(self):
481
559
        # prior to dirstate, st/diff/commit ignored nested trees.
482
 
        # dirstate, as opposed to dirstate-with-subtree, should
 
560
        # dirstate, as opposed to development-subtree, should
483
561
        # behave the same way.
484
562
        tree = self.make_branch_and_tree('.', format='dirstate')
485
563
        self.assertFalse(tree.supports_tree_reference())
525
603
        tree.unlock()
526
604
 
527
605
    def test_with_subtree_supports_tree_references(self):
528
 
        # dirstate-with-subtree should support tree-references.
529
 
        tree = self.make_branch_and_tree('.', format='dirstate-with-subtree')
 
606
        # development-subtree should support tree-references.
 
607
        tree = self.make_branch_and_tree('.', format='development-subtree')
530
608
        self.assertTrue(tree.supports_tree_reference())
531
609
        # having checked this is on, the tree interface, and intertree
532
610
        # interface tests, will proceed to test the subtree support of
595
673
                              tree_iter_changes, ['bar', 'foo'])
596
674
        self.assertEqual(e.paths, ['foo'])
597
675
 
 
676
    def test_iter_changes_unversioned_non_ascii(self):
 
677
        """Unversioned non-ascii paths should be reported as unicode"""
 
678
        self.requireFeature(features.UnicodeFilenameFeature)
 
679
        tree = self.make_branch_and_tree('.')
 
680
        self.build_tree_contents([('f', '')])
 
681
        tree.add(['f'], ['f-id'])
 
682
        def tree_iter_changes(tree, files):
 
683
            return list(tree.iter_changes(tree.basis_tree(),
 
684
                specific_files=files, require_versioned=True))
 
685
        tree.lock_read()
 
686
        self.addCleanup(tree.unlock)
 
687
        e = self.assertRaises(errors.PathsNotVersionedError,
 
688
            tree_iter_changes, tree, [u'\xa7', u'\u03c0'])
 
689
        self.assertEqual(e.paths, [u'\xa7', u'\u03c0'])
 
690
 
598
691
    def get_tree_with_cachable_file_foo(self):
599
692
        tree = self.make_branch_and_tree('.')
600
 
        self.build_tree(['foo'])
 
693
        tree.lock_write()
 
694
        self.addCleanup(tree.unlock)
 
695
        self.build_tree_contents([('foo', 'a bit of content for foo\n')])
601
696
        tree.add(['foo'], ['foo-id'])
602
 
        # a 4 second old timestamp is always hashable - sucks to delay
603
 
        # the test suite, but not testing this is worse.
604
 
        time.sleep(4)
 
697
        tree.current_dirstate()._cutoff_time = time.time() + 60
605
698
        return tree
606
699
 
607
700
    def test_commit_updates_hash_cache(self):
608
701
        tree = self.get_tree_with_cachable_file_foo()
609
702
        revid = tree.commit('a commit')
610
703
        # tree's dirstate should now have a valid stat entry for foo.
611
 
        tree.lock_read()
612
 
        self.addCleanup(tree.unlock)
613
704
        entry = tree._get_entry(path='foo')
614
705
        expected_sha1 = osutils.sha_file_by_name('foo')
615
706
        self.assertEqual(expected_sha1, entry[1][0][1])
 
707
        self.assertEqual(len('a bit of content for foo\n'), entry[1][0][2])
616
708
 
617
709
    def test_observed_sha1_cachable(self):
618
710
        tree = self.get_tree_with_cachable_file_foo()
619
711
        expected_sha1 = osutils.sha_file_by_name('foo')
620
712
        statvalue = os.lstat("foo")
621
 
        tree.lock_write()
622
 
        try:
623
 
            tree._observed_sha1("foo-id", "foo", (expected_sha1, statvalue))
624
 
            self.assertEqual(expected_sha1,
625
 
                tree._get_entry(path="foo")[1][0][1])
626
 
        finally:
627
 
            tree.unlock()
 
713
        tree._observed_sha1("foo-id", "foo", (expected_sha1, statvalue))
 
714
        entry = tree._get_entry(path="foo")
 
715
        entry_state = entry[1][0]
 
716
        self.assertEqual(expected_sha1, entry_state[1])
 
717
        self.assertEqual(statvalue.st_size, entry_state[2])
 
718
        tree.unlock()
 
719
        tree.lock_read()
628
720
        tree = tree.bzrdir.open_workingtree()
629
721
        tree.lock_read()
630
722
        self.addCleanup(tree.unlock)
631
 
        self.assertEqual(expected_sha1, tree._get_entry(path="foo")[1][0][1])
 
723
        entry = tree._get_entry(path="foo")
 
724
        entry_state = entry[1][0]
 
725
        self.assertEqual(expected_sha1, entry_state[1])
 
726
        self.assertEqual(statvalue.st_size, entry_state[2])
632
727
 
633
728
    def test_observed_sha1_new_file(self):
634
729
        tree = self.make_branch_and_tree('.')
771
866
        self.addCleanup(tree.unlock)
772
867
        # Force access to the in memory inventory to trigger bug #494221: try
773
868
        # maintaining the in-memory inventory
774
 
        inv = tree.inventory
 
869
        inv = tree.root_inventory
775
870
        self.assertTrue(inv.has_id('a-id'))
776
871
        self.assertTrue(inv.has_id('b-id'))
777
872
        tree.unversion(['a-id', 'b-id'])