~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Test the executable bit under various working tree formats."""
18
19
import os
20
2911.5.4 by John Arbash Meinel
Switch around to properly look up the executable bit in the basis.
21
from bzrlib import (
22
    osutils,
23
    )
1852.6.6 by Robert Collins
Finish updating iter_entries change to make all tests pass.
24
from bzrlib.inventory import InventoryFile
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
25
from bzrlib.transform import TreeTransform
26
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
27
28
29
class TestExecutable(TestCaseWithWorkingTree):
30
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
31
    def setUp(self):
32
        super(TestExecutable, self).setUp()
33
34
        self.a_id = "a-20051208024829-849e76f7968d7a86"
35
        self.b_id = "b-20051208024829-849e76f7968d7a86"
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
36
        wt = self.make_branch_and_tree('b1')
37
        b = wt.branch
38
        tt = TreeTransform(wt)
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
39
        tt.new_file('a', tt.root, 'a test\n', self.a_id, True)
40
        tt.new_file('b', tt.root, 'b test\n', self.b_id, False)
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
41
        tt.apply()
42
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
43
        self.wt = wt
44
45
    def check_exist(self, tree):
46
        """Just check that both files have the right executable bits set"""
2255.2.35 by Robert Collins
Remove inappropriate use of inventory in tree executability tests. The inventory is not the authoritative source of executability.
47
        tree.lock_read()
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
48
        self.failUnless(tree.is_executable(self.a_id),
49
                        "'a' lost the execute bit")
50
        self.failIf(tree.is_executable(self.b_id),
51
                    "'b' gained an execute bit")
2255.2.35 by Robert Collins
Remove inappropriate use of inventory in tree executability tests. The inventory is not the authoritative source of executability.
52
        tree.unlock()
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
53
54
    def check_empty(self, tree, ignore_inv=False):
55
        """Check that the files are truly missing
56
        :param ignore_inv: If you just delete files from a working tree
57
                the inventory still shows them, so don't assert that
58
                the inventory is empty, just that the tree doesn't have them
59
        """
2255.2.36 by Robert Collins
Fix Dirstate unversioning of entries which are in a parent.
60
        tree.lock_read()
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
61
        if not ignore_inv:
1852.6.6 by Robert Collins
Finish updating iter_entries change to make all tests pass.
62
            self.assertEqual(
63
                [('', tree.inventory.root)],
64
                list(tree.inventory.iter_entries()))
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
65
        self.failIf(tree.has_id(self.a_id))
66
        self.failIf(tree.has_filename('a'))
67
        self.failIf(tree.has_id(self.b_id))
68
        self.failIf(tree.has_filename('b'))
2255.2.36 by Robert Collins
Fix Dirstate unversioning of entries which are in a parent.
69
        tree.unlock()
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
70
71
    def commit_and_branch(self):
72
        """Commit the current tree, and create a second tree"""
73
        self.wt.commit('adding a,b', rev_id='r1')
74
        # Now make sure that 'bzr branch' also preserves the
75
        # executable bit
76
        # TODO: Maybe this should be a blackbox test
77
        dir2 = self.wt.branch.bzrdir.clone('b2', revision_id='r1')
78
        wt2 = dir2.open_workingtree()
1908.7.6 by Robert Collins
Deprecate WorkingTree.last_revision.
79
        self.assertEqual(['r1'], wt2.get_parent_ids())
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
80
        self.assertEqual('r1', wt2.branch.last_revision())
81
        return wt2
82
83
    def test_01_is_executable(self):
84
        """Make sure that the tree was created and has the executable bit set"""
85
        self.check_exist(self.wt)
86
87
    def test_02_stays_executable(self):
88
        """reopen the tree and ensure it stuck."""
89
        self.wt = self.wt.bzrdir.open_workingtree()
90
        self.check_exist(self.wt)
91
92
    def test_03_after_commit(self):
93
        """Commit the change, and check the history"""
94
        self.wt.commit('adding a,b', rev_id='r1')
95
96
        rev_tree = self.wt.branch.repository.revision_tree('r1')
97
        self.check_exist(rev_tree)
98
99
    def test_04_after_removed(self):
100
        """Make sure reverting removed files brings them back correctly"""
101
        self.wt.commit('adding a,b', rev_id='r1')
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
102
103
        # Make sure the entries are gone
104
        os.remove('b1/a')
105
        os.remove('b1/b')
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
106
        self.check_empty(self.wt, ignore_inv=True)
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
107
108
        # Make sure that revert is able to bring them back,
109
        # and sets 'a' back to being executable
110
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
111
        rev_tree = self.wt.branch.repository.revision_tree('r1')
112
113
        self.wt.revert(['a', 'b'], rev_tree, backups=False)
114
        self.check_exist(self.wt)
115
116
    def test_05_removed_and_committed(self):
117
        """Check that reverting to an earlier commit restores them"""
118
        self.wt.commit('adding a,b', rev_id='r1')
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
119
120
        # Now remove them again, and make sure that after a
121
        # commit, they are still marked correctly
122
        os.remove('b1/a')
123
        os.remove('b1/b')
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
124
        self.wt.commit('removed', rev_id='r2')
125
126
        self.check_empty(self.wt)
127
128
        rev_tree = self.wt.branch.repository.revision_tree('r1')
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
129
        # Now revert back to the previous commit
2748.3.2 by Aaron Bentley
Fix revert, remove-tree, and various tests to use None for 'no files specified'
130
        self.wt.revert(old_tree=rev_tree, backups=False)
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
131
132
        self.check_exist(self.wt)
133
134
    def test_06_branch(self):
135
        """branch b1=>b2 should preserve the executable bits"""
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
136
        # TODO: Maybe this should be a blackbox test
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
137
        wt2 = self.commit_and_branch()
138
139
        self.check_exist(wt2)
140
141
    def test_07_pull(self):
142
        """Test that pull will handle bits correctly"""
143
        wt2 = self.commit_and_branch()
144
145
        os.remove('b1/a')
146
        os.remove('b1/b')
147
        self.wt.commit('removed', rev_id='r2')
148
149
        # now wt2 can pull and the files should be removed
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
150
151
        # Make sure pull will delete the files
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
152
        wt2.pull(self.wt.branch)
1908.7.6 by Robert Collins
Deprecate WorkingTree.last_revision.
153
        self.assertEquals(['r2'], wt2.get_parent_ids())
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
154
        self.assertEquals('r2', wt2.branch.last_revision())
155
        self.check_empty(wt2)
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
156
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
157
        # Now restore the files on the first branch and commit
1711.4.30 by John Arbash Meinel
Don't peak under the covers, and test all working tree implementations for executable success (suggested by Robert Collins)
158
        # so that the second branch can pull the changes
159
        # and make sure that the executable bit has been copied
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
160
        rev_tree = self.wt.branch.repository.revision_tree('r1')
2748.3.2 by Aaron Bentley
Fix revert, remove-tree, and various tests to use None for 'no files specified'
161
        self.wt.revert(old_tree=rev_tree, backups=False)
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
162
        self.wt.commit('resurrected', rev_id='r3')
163
164
        self.check_exist(self.wt)
165
166
        wt2.pull(self.wt.branch)
1908.7.6 by Robert Collins
Deprecate WorkingTree.last_revision.
167
        self.assertEquals(['r3'], wt2.get_parent_ids())
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
168
        self.assertEquals('r3', wt2.branch.last_revision())
169
        self.check_exist(wt2)
170
171
    def test_08_no_op_revert(self):
172
        """Just do a simple revert without anything changed
173
        
174
        The bits shouldn't swap.
175
        """
176
        self.wt.commit('adding a,b', rev_id='r1')
177
        rev_tree = self.wt.branch.repository.revision_tree('r1')
2748.3.2 by Aaron Bentley
Fix revert, remove-tree, and various tests to use None for 'no files specified'
178
        self.wt.revert(old_tree=rev_tree, backups=False)
1711.4.33 by John Arbash Meinel
By Martin's suggestion, break the long test into lots of small ones.
179
        self.check_exist(self.wt)
180
2911.5.4 by John Arbash Meinel
Switch around to properly look up the executable bit in the basis.
181
    def test_commit_with_exec_from_basis(self):
182
        self.wt._is_executable_from_path_and_stat = \
183
            self.wt._is_executable_from_path_and_stat_from_basis
184
        rev_id1 = self.wt.commit('one')
185
        rev_tree1 = self.wt.branch.repository.revision_tree(rev_id1)
186
        a_executable = rev_tree1.inventory[self.a_id].executable
187
        b_executable = rev_tree1.inventory[self.b_id].executable
188
        self.assertIsNot(None, a_executable)
189
        self.assertTrue(a_executable)
190
        self.assertIsNot(None, b_executable)
191
        self.assertFalse(b_executable)
192
193
    def test_use_exec_from_basis(self):
194
        if osutils.supports_executable():
195
            self.assertEqual(self.wt._is_executable_from_path_and_stat_from_stat,
196
                             self.wt._is_executable_from_path_and_stat)
197
        else:
198
            self.assertEqual(self.wt._is_executable_from_path_and_stat_from_basis,
199
                             self.wt._is_executable_from_path_and_stat)