~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_permissions.py

  • Committer: Aaron Bentley
  • Date: 2007-04-11 00:16:09 UTC
  • mto: (2520.4.1 bzr.mpbundle)
  • mto: This revision was merged to the branch mainline in revision 2631.
  • Revision ID: aaron.bentley@utoronto.ca-20070411001609-fbx52la1yi0o3ui9
get add_version working

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
 
 
28
 
# TODO: jam 20051215 There are no tests for ftp yet, because we have no ftp server
29
 
# TODO: jam 20051215 Currently the default behavior for 'bzr branch' is just 
30
 
#                    defined by the local umask. This isn't terrible, is it
31
 
#                    the truly desired behavior?
32
 
 
33
 
import os
34
 
import sys
35
 
import stat
36
 
from StringIO import StringIO
37
 
 
38
 
from bzrlib.branch import Branch
39
 
from bzrlib.lockable_files import LockableFiles
40
 
from bzrlib.tests import TestCaseInTempDir, TestSkipped
41
 
from bzrlib.transport import get_transport
42
 
 
43
 
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
44
 
from bzrlib.transport import get_transport
45
 
 
46
 
 
47
 
def chmod_r(base, file_mode, dir_mode):
48
 
    """Recursively chmod from a base directory"""
49
 
    assert os.path.isdir(base)
50
 
    os.chmod(base, dir_mode)
51
 
    for root, dirs, files in os.walk(base):
52
 
        for d in dirs:
53
 
            p = os.path.join(root, d)
54
 
            os.chmod(p, dir_mode)
55
 
        for f in files:
56
 
            p = os.path.join(root, f)
57
 
            os.chmod(p, file_mode)
58
 
 
59
 
 
60
 
def check_mode_r(test, base, file_mode, dir_mode, include_base=True):
61
 
    """Check that all permissions match
62
 
 
63
 
    :param test: The TestCase being run
64
 
    :param base: The path to the root directory to check
65
 
    :param file_mode: The mode for all files
66
 
    :param dir_mode: The mode for all directories
67
 
    :param include_base: If false, only check the subdirectories
68
 
    """
69
 
    assert os.path.isdir(base)
70
 
    t = get_transport(".")
71
 
    if include_base:
72
 
        test.assertTransportMode(t, base, dir_mode)
73
 
    for root, dirs, files in os.walk(base):
74
 
        for d in dirs:
75
 
            p = os.path.join(root, d)
76
 
            test.assertTransportMode(t, p, dir_mode)
77
 
        for f in files:
78
 
            p = os.path.join(root, f)
79
 
            test.assertTransportMode(t, p, file_mode)
80
 
 
81
 
 
82
 
def assertEqualMode(test, mode, mode_test):
83
 
    test.assertEqual(mode, mode_test,
84
 
                     'mode mismatch %o != %o' % (mode, mode_test))
85
 
 
86
 
 
87
 
class TestPermissions(TestCaseInTempDir):
88
 
 
89
 
    def test_new_files(self):
90
 
        if sys.platform == 'win32':
91
 
            raise TestSkipped('chmod has no effect on win32')
92
 
 
93
 
        b = Branch.initialize(u'.')
94
 
        t = b.working_tree()
95
 
        open('a', 'wb').write('foo\n')
96
 
        t.add('a')
97
 
        t.commit('foo')
98
 
 
99
 
        # Delete them because we are modifying the filesystem underneath them
100
 
        del b, t 
101
 
        chmod_r('.bzr', 0644, 0755)
102
 
        check_mode_r(self, '.bzr', 0644, 0755)
103
 
 
104
 
        b = Branch.open('.')
105
 
        t = b.working_tree()
106
 
        assertEqualMode(self, 0755, b.control_files._dir_mode)
107
 
        assertEqualMode(self, 0644, b.control_files._file_mode)
108
 
 
109
 
        # Modifying a file shouldn't break the permissions
110
 
        open('a', 'wb').write('foo2\n')
111
 
        t.commit('foo2')
112
 
        # The mode should be maintained after commit
113
 
        check_mode_r(self, '.bzr', 0644, 0755)
114
 
 
115
 
        # Adding a new file should maintain the permissions
116
 
        open('b', 'wb').write('new b\n')
117
 
        t.add('b')
118
 
        t.commit('new b')
119
 
        check_mode_r(self, '.bzr', 0644, 0755)
120
 
 
121
 
        del b, t
122
 
        # Recursively update the modes of all files
123
 
        chmod_r('.bzr', 0664, 0775)
124
 
        check_mode_r(self, '.bzr', 0664, 0775)
125
 
        b = Branch.open('.')
126
 
        t = b.working_tree()
127
 
        assertEqualMode(self, 0775, b.control_files._dir_mode)
128
 
        assertEqualMode(self, 0664, b.control_files._file_mode)
129
 
 
130
 
        open('a', 'wb').write('foo3\n')
131
 
        t.commit('foo3')
132
 
        check_mode_r(self, '.bzr', 0664, 0775)
133
 
 
134
 
        open('c', 'wb').write('new c\n')
135
 
        t.add('c')
136
 
        t.commit('new c')
137
 
        check_mode_r(self, '.bzr', 0664, 0775)
138
 
 
139
 
        # Test the group sticky bit
140
 
        del b, t
141
 
        # Recursively update the modes of all files
142
 
        chmod_r('.bzr', 0664, 02775)
143
 
        check_mode_r(self, '.bzr', 0664, 02775)
144
 
        b = Branch.open('.')
145
 
        t = b.working_tree()
146
 
        assertEqualMode(self, 02775, b.control_files._dir_mode)
147
 
        assertEqualMode(self, 0664, b.control_files._file_mode)
148
 
 
149
 
        open('a', 'wb').write('foo4\n')
150
 
        t.commit('foo4')
151
 
        check_mode_r(self, '.bzr', 0664, 02775)
152
 
 
153
 
        open('d', 'wb').write('new d\n')
154
 
        t.add('d')
155
 
        t.commit('new d')
156
 
        check_mode_r(self, '.bzr', 0664, 02775)
157
 
 
158
 
    def test_disable_set_mode(self):
159
 
        # TODO: jam 20051215 Ultimately, this test should probably test that
160
 
        #                    extra chmod calls aren't being made
161
 
        try:
162
 
            transport = get_transport('.')
163
 
            transport.put('my-lock', StringIO(''))
164
 
            lockable = LockableFiles(transport, 'my-lock')
165
 
            self.assertNotEqual(None, lockable._dir_mode)
166
 
            self.assertNotEqual(None, lockable._file_mode)
167
 
 
168
 
            LockableFiles._set_dir_mode = False
169
 
            transport = get_transport('.')
170
 
            lockable = LockableFiles(transport, 'my-lock')
171
 
            self.assertEqual(None, lockable._dir_mode)
172
 
            self.assertNotEqual(None, lockable._file_mode)
173
 
 
174
 
            LockableFiles._set_file_mode = False
175
 
            transport = get_transport('.')
176
 
            lockable = LockableFiles(transport, 'my-lock')
177
 
            self.assertEqual(None, lockable._dir_mode)
178
 
            self.assertEqual(None, lockable._file_mode)
179
 
 
180
 
            LockableFiles._set_dir_mode = True
181
 
            transport = get_transport('.')
182
 
            lockable = LockableFiles(transport, 'my-lock')
183
 
            self.assertNotEqual(None, lockable._dir_mode)
184
 
            self.assertEqual(None, lockable._file_mode)
185
 
 
186
 
            LockableFiles._set_file_mode = True
187
 
            transport = get_transport('.')
188
 
            lockable = LockableFiles(transport, 'my-lock')
189
 
            self.assertNotEqual(None, lockable._dir_mode)
190
 
            self.assertNotEqual(None, lockable._file_mode)
191
 
        finally:
192
 
            LockableFiles._set_dir_mode = True
193
 
            LockableFiles._set_file_mode = True
194
 
 
195
 
    def test_new_branch(self):
196
 
        if sys.platform == 'win32':
197
 
            raise TestSkipped('chmod has no effect on win32')
198
 
        #FIXME RBC 20060105 should test branch and repository 
199
 
        # permissions ? 
200
 
        # also, these are BzrBranch format specific things..
201
 
        os.mkdir('a')
202
 
        mode = stat.S_IMODE(os.stat('a').st_mode)
203
 
        b = Branch.initialize('a')
204
 
        assertEqualMode(self, mode, b.control_files._dir_mode)
205
 
        assertEqualMode(self, mode & ~07111, b.control_files._file_mode)
206
 
 
207
 
        os.mkdir('b')
208
 
        os.chmod('b', 02777)
209
 
        b = Branch.initialize('b')
210
 
        assertEqualMode(self, 02777, b.control_files._dir_mode)
211
 
        assertEqualMode(self, 00666, b.control_files._file_mode)
212
 
        check_mode_r(self, 'b/.bzr', 00666, 02777)
213
 
 
214
 
        os.mkdir('c')
215
 
        os.chmod('c', 02750)
216
 
        b = Branch.initialize('c')
217
 
        assertEqualMode(self, 02750, b.control_files._dir_mode)
218
 
        assertEqualMode(self, 00640, b.control_files._file_mode)
219
 
        check_mode_r(self, 'c/.bzr', 00640, 02750)
220
 
 
221
 
        os.mkdir('d')
222
 
        os.chmod('d', 0700)
223
 
        b = Branch.initialize('d')
224
 
        assertEqualMode(self, 0700, b.control_files._dir_mode)
225
 
        assertEqualMode(self, 0600, b.control_files._file_mode)
226
 
        check_mode_r(self, 'd/.bzr', 00600, 0700)
227
 
 
228
 
 
229
 
class TestSftpPermissions(TestCaseWithSFTPServer):
230
 
 
231
 
    def test_new_files(self):
232
 
        if sys.platform == 'win32':
233
 
            raise TestSkipped('chmod has no effect on win32')
234
 
        # Though it would be nice to test that SFTP to a server
235
 
        # which does support chmod has the right effect
236
 
 
237
 
        from bzrlib.transport.sftp import SFTPTransport
238
 
 
239
 
        # We don't actually use it directly, we just want to
240
 
        # keep the connection open, since StubSFTPServer only
241
 
        # allows 1 connection
242
 
        _transport = SFTPTransport(self._sftp_url)
243
 
 
244
 
        os.mkdir('local')
245
 
        b_local = Branch.initialize(u'local')
246
 
        t_local = b_local.working_tree()
247
 
        open('local/a', 'wb').write('foo\n')
248
 
        t_local.add('a')
249
 
        t_local.commit('foo')
250
 
 
251
 
        # Delete them because we are modifying the filesystem underneath them
252
 
        del b_local, t_local 
253
 
        chmod_r('local/.bzr', 0644, 0755)
254
 
        check_mode_r(self, 'local/.bzr', 0644, 0755)
255
 
 
256
 
        b_local = Branch.open(u'local')
257
 
        t_local = b_local.working_tree()
258
 
        assertEqualMode(self, 0755, b_local.control_files._dir_mode)
259
 
        assertEqualMode(self, 0644, b_local.control_files._file_mode)
260
 
 
261
 
        os.mkdir('sftp')
262
 
        sftp_url = self.get_remote_url('sftp')
263
 
        b_sftp = Branch.initialize(sftp_url)
264
 
 
265
 
        b_sftp.pull(b_local)
266
 
        del b_sftp
267
 
        chmod_r('sftp/.bzr', 0644, 0755)
268
 
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
269
 
 
270
 
        b_sftp = Branch.open(sftp_url)
271
 
        assertEqualMode(self, 0755, b_sftp.control_files._dir_mode)
272
 
        assertEqualMode(self, 0644, b_sftp.control_files._file_mode)
273
 
 
274
 
        open('local/a', 'wb').write('foo2\n')
275
 
        t_local.commit('foo2')
276
 
        b_sftp.pull(b_local)
277
 
        # The mode should be maintained after commit
278
 
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
279
 
 
280
 
        open('local/b', 'wb').write('new b\n')
281
 
        t_local.add('b')
282
 
        t_local.commit('new b')
283
 
        b_sftp.pull(b_local)
284
 
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
285
 
 
286
 
        del b_sftp
287
 
        # Recursively update the modes of all files
288
 
        chmod_r('sftp/.bzr', 0664, 0775)
289
 
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
290
 
 
291
 
        b_sftp = Branch.open(sftp_url)
292
 
        assertEqualMode(self, 0775, b_sftp.control_files._dir_mode)
293
 
        assertEqualMode(self, 0664, b_sftp.control_files._file_mode)
294
 
 
295
 
        open('local/a', 'wb').write('foo3\n')
296
 
        t_local.commit('foo3')
297
 
        b_sftp.pull(b_local)
298
 
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
299
 
 
300
 
        open('local/c', 'wb').write('new c\n')
301
 
        t_local.add('c')
302
 
        t_local.commit('new c')
303
 
        b_sftp.pull(b_local)
304
 
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
305
 
 
306
 
    def test_sftp_server_modes(self):
307
 
        if sys.platform == 'win32':
308
 
            raise TestSkipped('chmod has no effect on win32')
309
 
 
310
 
        umask = 0022
311
 
        original_umask = os.umask(umask)
312
 
 
313
 
        try:
314
 
            from bzrlib.transport.sftp import SFTPTransport
315
 
            t = SFTPTransport(self._sftp_url)
316
 
            # Direct access should be masked by umask
317
 
            t._sftp_open_exclusive('a', mode=0666).write('foo\n')
318
 
            self.assertTransportMode(t, 'a', 0666 &~umask)
319
 
 
320
 
            # but Transport overrides umask
321
 
            t.put('b', 'txt', mode=0666)
322
 
            self.assertTransportMode(t, 'b', 0666)
323
 
 
324
 
            t._sftp.mkdir('c', mode=0777)
325
 
            self.assertTransportMode(t, 'c', 0777 &~umask)
326
 
 
327
 
            t.mkdir('d', mode=0777)
328
 
            self.assertTransportMode(t, 'd', 0777)
329
 
        finally:
330
 
            os.umask(original_umask)
331
 
 
332