/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_permissions.py

merge integration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005 by Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
 
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
 
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 
 
18
 
 
19
"""Tests for bzr setting permissions.
 
20
 
 
21
Files which are created underneath .bzr/ should inherit its permissions.
 
22
So if the directory is group writable, the files and subdirs should be as well.
 
23
 
 
24
In the future, when we have Repository/Branch/Checkout information, the
 
25
permissions should be inherited individually, rather than all be the same.
 
26
 
 
27
TODO: jam 20051215 There are no tests for ftp yet, because we have no ftp server
 
28
TODO: jam 20051215 Currently the default behavior for 'bzr branch' is just 
 
29
                   defined by the local umask. This isn't terrible, is it
 
30
                   the truly desired behavior?
 
31
"""
 
32
 
 
33
import os
 
34
import sys
 
35
import stat
 
36
 
 
37
from bzrlib.branch import Branch
 
38
from bzrlib.tests import TestCaseInTempDir, TestSkipped
 
39
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
 
40
from bzrlib.tests.test_transport import check_mode
 
41
 
 
42
 
 
43
def chmod_r(base, file_mode, dir_mode):
 
44
    """Recursively chmod from a base directory"""
 
45
    assert os.path.isdir(base)
 
46
    os.chmod(base, dir_mode)
 
47
    for root, dirs, files in os.walk(base):
 
48
        for d in dirs:
 
49
            p = os.path.join(root, d)
 
50
            os.chmod(p, dir_mode)
 
51
        for f in files:
 
52
            p = os.path.join(root, f)
 
53
            os.chmod(p, file_mode)
 
54
 
 
55
 
 
56
def check_mode_r(test, base, file_mode, dir_mode, include_base=True):
 
57
    """Check that all permissions match
 
58
 
 
59
    :param test: The TestCase being run
 
60
    :param base: The path to the root directory to check
 
61
    :param file_mode: The mode for all files
 
62
    :param dir_mode: The mode for all directories
 
63
    :param include_base: If false, only check the subdirectories
 
64
    """
 
65
    assert os.path.isdir(base)
 
66
    if include_base:
 
67
        check_mode(test, base, dir_mode)
 
68
    for root, dirs, files in os.walk(base):
 
69
        for d in dirs:
 
70
            p = os.path.join(root, d)
 
71
            check_mode(test, p, dir_mode)
 
72
        for f in files:
 
73
            p = os.path.join(root, f)
 
74
            check_mode(test, p, file_mode)
 
75
 
 
76
 
 
77
def assertEqualMode(test, mode, mode_test):
 
78
    test.assertEqual(mode, mode_test,
 
79
                     'mode mismatch %o != %o' % (mode, mode_test))
 
80
 
 
81
 
 
82
class TestPermissions(TestCaseInTempDir):
 
83
 
 
84
    def test_new_files(self):
 
85
        if sys.platform == 'win32':
 
86
            raise TestSkipped('chmod has no effect on win32')
 
87
 
 
88
        b = Branch.initialize(u'.')
 
89
        t = b.working_tree()
 
90
        open('a', 'wb').write('foo\n')
 
91
        t.add('a')
 
92
        t.commit('foo')
 
93
 
 
94
        # Delete them because we are modifying the filesystem underneath them
 
95
        del b, t 
 
96
        chmod_r('.bzr', 0644, 0755)
 
97
        check_mode_r(self, '.bzr', 0644, 0755)
 
98
 
 
99
        b = Branch.open('.')
 
100
        t = b.working_tree()
 
101
        assertEqualMode(self, 0755, b._dir_mode)
 
102
        assertEqualMode(self, 0644, b._file_mode)
 
103
 
 
104
        # Modifying a file shouldn't break the permissions
 
105
        open('a', 'wb').write('foo2\n')
 
106
        t.commit('foo2')
 
107
        # The mode should be maintained after commit
 
108
        check_mode_r(self, '.bzr', 0644, 0755)
 
109
 
 
110
        # Adding a new file should maintain the permissions
 
111
        open('b', 'wb').write('new b\n')
 
112
        t.add('b')
 
113
        t.commit('new b')
 
114
        check_mode_r(self, '.bzr', 0644, 0755)
 
115
 
 
116
        del b, t
 
117
        # Recursively update the modes of all files
 
118
        chmod_r('.bzr', 0664, 0775)
 
119
        check_mode_r(self, '.bzr', 0664, 0775)
 
120
        b = Branch.open('.')
 
121
        t = b.working_tree()
 
122
        assertEqualMode(self, 0775, b._dir_mode)
 
123
        assertEqualMode(self, 0664, b._file_mode)
 
124
 
 
125
        open('a', 'wb').write('foo3\n')
 
126
        t.commit('foo3')
 
127
        check_mode_r(self, '.bzr', 0664, 0775)
 
128
 
 
129
        open('c', 'wb').write('new c\n')
 
130
        t.add('c')
 
131
        t.commit('new c')
 
132
        check_mode_r(self, '.bzr', 0664, 0775)
 
133
 
 
134
        # Test the group sticky bit
 
135
        del b, t
 
136
        # Recursively update the modes of all files
 
137
        chmod_r('.bzr', 0664, 02775)
 
138
        check_mode_r(self, '.bzr', 0664, 02775)
 
139
        b = Branch.open('.')
 
140
        t = b.working_tree()
 
141
        assertEqualMode(self, 02775, b._dir_mode)
 
142
        assertEqualMode(self, 0664, b._file_mode)
 
143
 
 
144
        open('a', 'wb').write('foo4\n')
 
145
        t.commit('foo4')
 
146
        check_mode_r(self, '.bzr', 0664, 02775)
 
147
 
 
148
        open('d', 'wb').write('new d\n')
 
149
        t.add('d')
 
150
        t.commit('new d')
 
151
        check_mode_r(self, '.bzr', 0664, 02775)
 
152
 
 
153
    def test_disable_set_mode(self):
 
154
        # TODO: jam 20051215 Ultimately, this test should probably test that
 
155
        #                    extra chmod calls aren't being made
 
156
        import bzrlib.branch
 
157
        try:
 
158
            b = Branch.initialize(u'.')
 
159
            self.assertNotEqual(None, b._dir_mode)
 
160
            self.assertNotEqual(None, b._file_mode)
 
161
 
 
162
            bzrlib.branch.BzrBranch._set_dir_mode = False
 
163
            b = Branch.open(u'.')
 
164
            self.assertEqual(None, b._dir_mode)
 
165
            self.assertNotEqual(None, b._file_mode)
 
166
 
 
167
            bzrlib.branch.BzrBranch._set_file_mode = False
 
168
            b = Branch.open(u'.')
 
169
            self.assertEqual(None, b._dir_mode)
 
170
            self.assertEqual(None, b._file_mode)
 
171
 
 
172
            bzrlib.branch.BzrBranch._set_dir_mode = True
 
173
            b = Branch.open(u'.')
 
174
            self.assertNotEqual(None, b._dir_mode)
 
175
            self.assertEqual(None, b._file_mode)
 
176
 
 
177
            bzrlib.branch.BzrBranch._set_file_mode = True
 
178
            b = Branch.open(u'.')
 
179
            self.assertNotEqual(None, b._dir_mode)
 
180
            self.assertNotEqual(None, b._file_mode)
 
181
        finally:
 
182
            bzrlib.branch.BzrBranch._set_dir_mode = True
 
183
            bzrlib.branch.BzrBranch._set_file_mode = True
 
184
 
 
185
    def test_new_branch(self):
 
186
        if sys.platform == 'win32':
 
187
            raise TestSkipped('chmod has no effect on win32')
 
188
 
 
189
        os.mkdir('a')
 
190
        mode = stat.S_IMODE(os.stat('a').st_mode)
 
191
        b = Branch.initialize('a')
 
192
        assertEqualMode(self, mode, b._dir_mode)
 
193
        assertEqualMode(self, mode & ~07111, b._file_mode)
 
194
 
 
195
        os.mkdir('b')
 
196
        os.chmod('b', 02777)
 
197
        b = Branch.initialize('b')
 
198
        assertEqualMode(self, 02777, b._dir_mode)
 
199
        assertEqualMode(self, 00666, b._file_mode)
 
200
        check_mode_r(self, 'b/.bzr', 00666, 02777)
 
201
 
 
202
        os.mkdir('c')
 
203
        os.chmod('c', 02750)
 
204
        b = Branch.initialize('c')
 
205
        assertEqualMode(self, 02750, b._dir_mode)
 
206
        assertEqualMode(self, 00640, b._file_mode)
 
207
        check_mode_r(self, 'c/.bzr', 00640, 02750)
 
208
 
 
209
        os.mkdir('d')
 
210
        os.chmod('d', 0700)
 
211
        b = Branch.initialize('d')
 
212
        assertEqualMode(self, 0700, b._dir_mode)
 
213
        assertEqualMode(self, 0600, b._file_mode)
 
214
        check_mode_r(self, 'd/.bzr', 00600, 0700)
 
215
 
 
216
 
 
217
class TestSftpPermissions(TestCaseWithSFTPServer):
 
218
 
 
219
    def test_new_files(self):
 
220
        if sys.platform == 'win32':
 
221
            raise TestSkipped('chmod has no effect on win32')
 
222
        # Though it would be nice to test that SFTP to a server
 
223
        # which does support chmod has the right effect
 
224
 
 
225
        from bzrlib.transport.sftp import SFTPTransport
 
226
 
 
227
        # We don't actually use it directly, we just want to
 
228
        # keep the connection open, since StubSFTPServer only
 
229
        # allows 1 connection
 
230
        _transport = SFTPTransport(self._sftp_url)
 
231
 
 
232
        os.mkdir('local')
 
233
        b_local = Branch.initialize(u'local')
 
234
        t_local = b_local.working_tree()
 
235
        open('local/a', 'wb').write('foo\n')
 
236
        t_local.add('a')
 
237
        t_local.commit('foo')
 
238
 
 
239
        # Delete them because we are modifying the filesystem underneath them
 
240
        del b_local, t_local 
 
241
        chmod_r('local/.bzr', 0644, 0755)
 
242
        check_mode_r(self, 'local/.bzr', 0644, 0755)
 
243
 
 
244
        b_local = Branch.open(u'local')
 
245
        t_local = b_local.working_tree()
 
246
        assertEqualMode(self, 0755, b_local._dir_mode)
 
247
        assertEqualMode(self, 0644, b_local._file_mode)
 
248
 
 
249
        os.mkdir('sftp')
 
250
        sftp_url = self.get_remote_url('sftp')
 
251
        b_sftp = Branch.initialize(sftp_url)
 
252
 
 
253
        b_sftp.pull(b_local)
 
254
        del b_sftp
 
255
        chmod_r('sftp/.bzr', 0644, 0755)
 
256
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
 
257
 
 
258
        b_sftp = Branch.open(sftp_url)
 
259
        assertEqualMode(self, 0755, b_sftp._dir_mode)
 
260
        assertEqualMode(self, 0644, b_sftp._file_mode)
 
261
 
 
262
        open('local/a', 'wb').write('foo2\n')
 
263
        t_local.commit('foo2')
 
264
        b_sftp.pull(b_local)
 
265
        # The mode should be maintained after commit
 
266
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
 
267
 
 
268
        open('local/b', 'wb').write('new b\n')
 
269
        t_local.add('b')
 
270
        t_local.commit('new b')
 
271
        b_sftp.pull(b_local)
 
272
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
 
273
 
 
274
        del b_sftp
 
275
        # Recursively update the modes of all files
 
276
        chmod_r('sftp/.bzr', 0664, 0775)
 
277
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
 
278
 
 
279
        b_sftp = Branch.open(sftp_url)
 
280
        assertEqualMode(self, 0775, b_sftp._dir_mode)
 
281
        assertEqualMode(self, 0664, b_sftp._file_mode)
 
282
 
 
283
        open('local/a', 'wb').write('foo3\n')
 
284
        t_local.commit('foo3')
 
285
        b_sftp.pull(b_local)
 
286
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
 
287
 
 
288
        open('local/c', 'wb').write('new c\n')
 
289
        t_local.add('c')
 
290
        t_local.commit('new c')
 
291
        b_sftp.pull(b_local)
 
292
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
 
293
 
 
294
    def test_sftp_server_modes(self):
 
295
        if sys.platform == 'win32':
 
296
            raise TestSkipped('chmod has no effect on win32')
 
297
 
 
298
        umask = 0022
 
299
        original_umask = os.umask(umask)
 
300
 
 
301
        try:
 
302
            from bzrlib.transport.sftp import SFTPTransport
 
303
            t = SFTPTransport(self._sftp_url)
 
304
            # Direct access should be masked by umask
 
305
            t._sftp_open_exclusive('a', mode=0666).write('foo\n')
 
306
            check_mode(self, 'a', 0666 &~umask)
 
307
 
 
308
            # but Transport overrides umask
 
309
            t.put('b', 'txt', mode=0666)
 
310
            check_mode(self, 'b', 0666)
 
311
 
 
312
            t._sftp.mkdir('c', mode=0777)
 
313
            check_mode(self, 'c', 0777 &~umask)
 
314
 
 
315
            t.mkdir('d', mode=0777)
 
316
            check_mode(self, 'd', 0777)
 
317
        finally:
 
318
            os.umask(original_umask)
 
319
 
 
320