~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_permissions.py

[merge] jam-integration

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005 by Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
 
#
 
3
 
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
6
6
# the Free Software Foundation; either version 2 of the License, or
7
7
# (at your option) any later version.
8
 
#
 
8
 
9
9
# This program is distributed in the hope that it will be useful,
10
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
12
# GNU General Public License for more details.
13
 
#
 
13
 
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33
33
import os
34
34
import sys
35
35
import stat
36
 
from cStringIO import StringIO
37
 
import urllib
 
36
from StringIO import StringIO
38
37
 
39
38
from bzrlib.branch import Branch
40
 
from bzrlib.bzrdir import BzrDir
41
 
from bzrlib.lockable_files import LockableFiles, TransportLock
 
39
from bzrlib.lockable_files import LockableFiles
42
40
from bzrlib.tests import TestCaseWithTransport, TestSkipped
43
41
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
44
42
from bzrlib.transport import get_transport
73
71
        test.assertTransportMode(t, base, dir_mode)
74
72
    for root, dirs, files in os.walk(base):
75
73
        for d in dirs:
76
 
            p = '/'.join([urllib.quote(x) for x in root.split('/\\') + [d]])
 
74
            p = os.path.join(root, d)
77
75
            test.assertTransportMode(t, p, dir_mode)
78
76
        for f in files:
79
77
            p = os.path.join(root, f)
80
 
            p = '/'.join([urllib.quote(x) for x in root.split('/\\') + [f]])
81
78
            test.assertTransportMode(t, p, file_mode)
82
79
 
83
80
 
 
81
def assertEqualMode(test, mode, mode_test):
 
82
    test.assertEqual(mode, mode_test,
 
83
                     'mode mismatch %o != %o' % (mode, mode_test))
 
84
 
 
85
 
84
86
class TestPermissions(TestCaseWithTransport):
85
87
 
86
88
    def test_new_files(self):
87
89
        if sys.platform == 'win32':
88
90
            raise TestSkipped('chmod has no effect on win32')
89
91
 
90
 
        t = self.make_branch_and_tree('.')
 
92
        t = WorkingTree.create_standalone('.')
91
93
        b = t.branch
92
94
        open('a', 'wb').write('foo\n')
93
 
        # ensure check_mode_r works with capital-letter file-ids like TREE_ROOT
94
 
        t.add('a', 'CAPS-ID')
 
95
        t.add('a')
95
96
        t.commit('foo')
96
97
 
 
98
        # Delete them because we are modifying the filesystem underneath them
 
99
        del b, t 
97
100
        chmod_r('.bzr', 0644, 0755)
98
101
        check_mode_r(self, '.bzr', 0644, 0755)
99
102
 
100
 
        # although we are modifying the filesystem
101
 
        # underneath the objects, they are not locked, and thus it must
102
 
        # be safe for most operations. But here we want to observe a 
103
 
        # mode change in the control bits, which current do not refresh
104
 
        # when a new lock is taken out.
105
 
        t = WorkingTree.open('.')
106
 
        b = t.branch
107
 
        self.assertEqualMode(0755, b.control_files._dir_mode)
108
 
        self.assertEqualMode(0644, b.control_files._file_mode)
 
103
        b = Branch.open('.')
 
104
        t = b.working_tree()
 
105
        assertEqualMode(self, 0755, b.control_files._dir_mode)
 
106
        assertEqualMode(self, 0644, b.control_files._file_mode)
109
107
 
110
108
        # Modifying a file shouldn't break the permissions
111
109
        open('a', 'wb').write('foo2\n')
119
117
        t.commit('new b')
120
118
        check_mode_r(self, '.bzr', 0644, 0755)
121
119
 
 
120
        del b, t
122
121
        # Recursively update the modes of all files
123
122
        chmod_r('.bzr', 0664, 0775)
124
123
        check_mode_r(self, '.bzr', 0664, 0775)
125
 
        t = WorkingTree.open('.')
126
 
        b = t.branch
127
 
        self.assertEqualMode(0775, b.control_files._dir_mode)
128
 
        self.assertEqualMode(0664, b.control_files._file_mode)
 
124
        b = Branch.open('.')
 
125
        t = b.working_tree()
 
126
        assertEqualMode(self, 0775, b.control_files._dir_mode)
 
127
        assertEqualMode(self, 0664, b.control_files._file_mode)
129
128
 
130
129
        open('a', 'wb').write('foo3\n')
131
130
        t.commit('foo3')
137
136
        check_mode_r(self, '.bzr', 0664, 0775)
138
137
 
139
138
        # Test the group sticky bit
 
139
        del b, t
140
140
        # Recursively update the modes of all files
141
141
        chmod_r('.bzr', 0664, 02775)
142
142
        check_mode_r(self, '.bzr', 0664, 02775)
143
 
        t = WorkingTree.open('.')
144
 
        b = t.branch
145
 
        self.assertEqualMode(02775, b.control_files._dir_mode)
146
 
        self.assertEqualMode(0664, b.control_files._file_mode)
 
143
        b = Branch.open('.')
 
144
        t = b.working_tree()
 
145
        assertEqualMode(self, 02775, b.control_files._dir_mode)
 
146
        assertEqualMode(self, 0664, b.control_files._file_mode)
147
147
 
148
148
        open('a', 'wb').write('foo4\n')
149
149
        t.commit('foo4')
159
159
        #                    extra chmod calls aren't being made
160
160
        try:
161
161
            transport = get_transport(self.get_url())
162
 
            transport.put_bytes('my-lock', '')
163
 
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
162
            transport.put('my-lock', StringIO(''))
 
163
            lockable = LockableFiles(transport, 'my-lock')
164
164
            self.assertNotEqual(None, lockable._dir_mode)
165
165
            self.assertNotEqual(None, lockable._file_mode)
166
166
 
167
167
            LockableFiles._set_dir_mode = False
168
168
            transport = get_transport('.')
169
 
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
169
            lockable = LockableFiles(transport, 'my-lock')
170
170
            self.assertEqual(None, lockable._dir_mode)
171
171
            self.assertNotEqual(None, lockable._file_mode)
172
172
 
173
173
            LockableFiles._set_file_mode = False
174
174
            transport = get_transport('.')
175
 
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
175
            lockable = LockableFiles(transport, 'my-lock')
176
176
            self.assertEqual(None, lockable._dir_mode)
177
177
            self.assertEqual(None, lockable._file_mode)
178
178
 
179
179
            LockableFiles._set_dir_mode = True
180
180
            transport = get_transport('.')
181
 
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
181
            lockable = LockableFiles(transport, 'my-lock')
182
182
            self.assertNotEqual(None, lockable._dir_mode)
183
183
            self.assertEqual(None, lockable._file_mode)
184
184
 
185
185
            LockableFiles._set_file_mode = True
186
186
            transport = get_transport('.')
187
 
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
187
            lockable = LockableFiles(transport, 'my-lock')
188
188
            self.assertNotEqual(None, lockable._dir_mode)
189
189
            self.assertNotEqual(None, lockable._file_mode)
190
190
        finally:
191
191
            LockableFiles._set_dir_mode = True
192
192
            LockableFiles._set_file_mode = True
193
193
 
 
194
    def test_new_branch(self):
 
195
        if sys.platform == 'win32':
 
196
            raise TestSkipped('chmod has no effect on win32')
 
197
        #FIXME RBC 20060105 should test branch and repository 
 
198
        # permissions ? 
 
199
        # also, these are BzrBranch format specific things..
 
200
        os.mkdir('a')
 
201
        mode = stat.S_IMODE(os.stat('a').st_mode)
 
202
        t = WorkingTree.create_standalone('.')
 
203
        b = t.branch
 
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.create('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.create('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.create('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
 
194
228
 
195
229
class TestSftpPermissions(TestCaseWithSFTPServer):
196
230
 
200
234
        # Though it would be nice to test that SFTP to a server
201
235
        # which does support chmod has the right effect
202
236
 
203
 
        # bodge around for stubsftpserver not letting use connect
204
 
        # more than once
205
 
        _t = get_transport(self.get_url())
 
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)
206
243
 
207
244
        os.mkdir('local')
208
 
        t_local = self.make_branch_and_tree('local')
 
245
        t_local = WorkingTree.create_standalone('local')
209
246
        b_local = t_local.branch
210
247
        open('local/a', 'wb').write('foo\n')
211
248
        t_local.add('a')
212
249
        t_local.commit('foo')
213
250
 
214
251
        # Delete them because we are modifying the filesystem underneath them
 
252
        del b_local, t_local 
215
253
        chmod_r('local/.bzr', 0644, 0755)
216
254
        check_mode_r(self, 'local/.bzr', 0644, 0755)
217
255
 
218
 
        t = WorkingTree.open('local')
219
 
        b_local = t.branch
220
 
        self.assertEqualMode(0755, b_local.control_files._dir_mode)
221
 
        self.assertEqualMode(0644, b_local.control_files._file_mode)
 
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)
222
260
 
223
261
        os.mkdir('sftp')
224
 
        sftp_url = self.get_url('sftp')
225
 
        b_sftp = BzrDir.create_branch_and_repo(sftp_url)
 
262
        sftp_url = self.get_remote_url('sftp')
 
263
        b_sftp = Branch.create(sftp_url)
226
264
 
227
265
        b_sftp.pull(b_local)
228
266
        del b_sftp
230
268
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
231
269
 
232
270
        b_sftp = Branch.open(sftp_url)
233
 
        self.assertEqualMode(0755, b_sftp.control_files._dir_mode)
234
 
        self.assertEqualMode(0644, b_sftp.control_files._file_mode)
 
271
        assertEqualMode(self, 0755, b_sftp.control_files._dir_mode)
 
272
        assertEqualMode(self, 0644, b_sftp.control_files._file_mode)
235
273
 
236
274
        open('local/a', 'wb').write('foo2\n')
237
275
        t_local.commit('foo2')
251
289
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
252
290
 
253
291
        b_sftp = Branch.open(sftp_url)
254
 
        self.assertEqualMode(0775, b_sftp.control_files._dir_mode)
255
 
        self.assertEqualMode(0664, b_sftp.control_files._file_mode)
 
292
        assertEqualMode(self, 0775, b_sftp.control_files._dir_mode)
 
293
        assertEqualMode(self, 0664, b_sftp.control_files._file_mode)
256
294
 
257
295
        open('local/a', 'wb').write('foo3\n')
258
296
        t_local.commit('foo3')
273
311
        original_umask = os.umask(umask)
274
312
 
275
313
        try:
276
 
            t = get_transport(self.get_url())
 
314
            from bzrlib.transport.sftp import SFTPTransport
 
315
            t = SFTPTransport(self._sftp_url)
277
316
            # Direct access should be masked by umask
278
317
            t._sftp_open_exclusive('a', mode=0666).write('foo\n')
279
318
            self.assertTransportMode(t, 'a', 0666 &~umask)
280
319
 
281
320
            # but Transport overrides umask
282
 
            t.put_bytes('b', 'txt', mode=0666)
 
321
            t.put('b', 'txt', mode=0666)
283
322
            self.assertTransportMode(t, 'b', 0666)
284
323
 
285
 
            t._get_sftp().mkdir('c', mode=0777)
 
324
            t._sftp.mkdir('c', mode=0777)
286
325
            self.assertTransportMode(t, 'c', 0777 &~umask)
287
326
 
288
327
            t.mkdir('d', mode=0777)