~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_permissions.py

Merge up bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005 Canonical Ltd
2
2
# -*- coding: utf-8 -*-
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
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
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
 
18
18
 
19
19
"""Tests for bzr setting permissions.
26
26
"""
27
27
 
28
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
 
29
# TODO: jam 20051215 Currently the default behavior for 'bzr branch' is just 
30
30
#                    defined by the local umask. This isn't terrible, is it
31
31
#                    the truly desired behavior?
32
 
 
 
32
 
33
33
import os
34
34
import sys
 
35
import stat
 
36
from cStringIO import StringIO
 
37
import urllib
35
38
 
36
 
from bzrlib import urlutils
37
39
from bzrlib.branch import Branch
38
 
from bzrlib.controldir import ControlDir
 
40
from bzrlib.bzrdir import BzrDir
 
41
from bzrlib.lockable_files import LockableFiles, TransportLock
39
42
from bzrlib.tests import TestCaseWithTransport, TestSkipped
40
43
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
 
44
from bzrlib.transport import get_transport
41
45
from bzrlib.workingtree import WorkingTree
42
46
 
43
47
 
62
66
    :param dir_mode: The mode for all directories
63
67
    :param include_base: If false, only check the subdirectories
64
68
    """
65
 
    t = test.get_transport()
 
69
    t = get_transport(".")
66
70
    if include_base:
67
71
        test.assertTransportMode(t, base, dir_mode)
68
72
    for root, dirs, files in os.walk(base):
69
73
        for d in dirs:
70
 
            p = '/'.join([urlutils.quote(x) for x in root.split('/\\') + [d]])
 
74
            p = '/'.join([urllib.quote(x) for x in root.split('/\\') + [d]])
71
75
            test.assertTransportMode(t, p, dir_mode)
72
76
        for f in files:
73
77
            p = os.path.join(root, f)
74
 
            p = '/'.join([urlutils.quote(x) for x in root.split('/\\') + [f]])
 
78
            p = '/'.join([urllib.quote(x) for x in root.split('/\\') + [f]])
75
79
            test.assertTransportMode(t, p, file_mode)
76
80
 
77
81
 
83
87
 
84
88
        t = self.make_branch_and_tree('.')
85
89
        b = t.branch
86
 
        with open('a', 'wb') as f: f.write('foo\n')
 
90
        open('a', 'wb').write('foo\n')
87
91
        # ensure check_mode_r works with capital-letter file-ids like TREE_ROOT
88
92
        t.add('a', 'CAPS-ID')
89
93
        t.commit('foo')
93
97
 
94
98
        # although we are modifying the filesystem
95
99
        # underneath the objects, they are not locked, and thus it must
96
 
        # be safe for most operations. But here we want to observe a
 
100
        # be safe for most operations. But here we want to observe a 
97
101
        # mode change in the control bits, which current do not refresh
98
102
        # when a new lock is taken out.
99
103
        t = WorkingTree.open('.')
100
104
        b = t.branch
101
105
        self.assertEqualMode(0755, b.control_files._dir_mode)
102
106
        self.assertEqualMode(0644, b.control_files._file_mode)
103
 
        self.assertEqualMode(0755, b.bzrdir._get_dir_mode())
104
 
        self.assertEqualMode(0644, b.bzrdir._get_file_mode())
105
107
 
106
108
        # Modifying a file shouldn't break the permissions
107
 
        with open('a', 'wb') as f: f.write('foo2\n')
 
109
        open('a', 'wb').write('foo2\n')
108
110
        t.commit('foo2')
109
111
        # The mode should be maintained after commit
110
112
        check_mode_r(self, '.bzr', 0644, 0755)
111
113
 
112
114
        # Adding a new file should maintain the permissions
113
 
        with open('b', 'wb') as f: f.write('new b\n')
 
115
        open('b', 'wb').write('new b\n')
114
116
        t.add('b')
115
117
        t.commit('new b')
116
118
        check_mode_r(self, '.bzr', 0644, 0755)
122
124
        b = t.branch
123
125
        self.assertEqualMode(0775, b.control_files._dir_mode)
124
126
        self.assertEqualMode(0664, b.control_files._file_mode)
125
 
        self.assertEqualMode(0775, b.bzrdir._get_dir_mode())
126
 
        self.assertEqualMode(0664, b.bzrdir._get_file_mode())
127
127
 
128
 
        with open('a', 'wb') as f: f.write('foo3\n')
 
128
        open('a', 'wb').write('foo3\n')
129
129
        t.commit('foo3')
130
130
        check_mode_r(self, '.bzr', 0664, 0775)
131
131
 
132
 
        with open('c', 'wb') as f: f.write('new c\n')
 
132
        open('c', 'wb').write('new c\n')
133
133
        t.add('c')
134
134
        t.commit('new c')
135
135
        check_mode_r(self, '.bzr', 0664, 0775)
136
136
 
137
 
    def test_new_files_group_sticky_bit(self):
138
 
        if sys.platform == 'win32':
139
 
            raise TestSkipped('chmod has no effect on win32')
140
 
        elif sys.platform == 'darwin' or 'freebsd' in sys.platform:
141
 
            # FreeBSD-based platforms create temp dirs with the 'wheel' group,
142
 
            # which users are not likely to be in, and this prevents us from
143
 
            # setting the sgid bit
144
 
            os.chown(self.test_dir, os.getuid(), os.getgid())
145
 
 
146
 
        t = self.make_branch_and_tree('.')
147
 
        b = t.branch
148
 
 
149
137
        # Test the group sticky bit
150
138
        # Recursively update the modes of all files
151
139
        chmod_r('.bzr', 0664, 02775)
154
142
        b = t.branch
155
143
        self.assertEqualMode(02775, b.control_files._dir_mode)
156
144
        self.assertEqualMode(0664, b.control_files._file_mode)
157
 
        self.assertEqualMode(02775, b.bzrdir._get_dir_mode())
158
 
        self.assertEqualMode(0664, b.bzrdir._get_file_mode())
159
145
 
160
 
        with open('a', 'wb') as f: f.write('foo4\n')
 
146
        open('a', 'wb').write('foo4\n')
161
147
        t.commit('foo4')
162
148
        check_mode_r(self, '.bzr', 0664, 02775)
163
149
 
164
 
        with open('d', 'wb') as f: f.write('new d\n')
 
150
        open('d', 'wb').write('new d\n')
165
151
        t.add('d')
166
152
        t.commit('new d')
167
153
        check_mode_r(self, '.bzr', 0664, 02775)
168
154
 
 
155
    def test_disable_set_mode(self):
 
156
        # TODO: jam 20051215 Ultimately, this test should probably test that
 
157
        #                    extra chmod calls aren't being made
 
158
        try:
 
159
            transport = get_transport(self.get_url())
 
160
            transport.put_bytes('my-lock', '')
 
161
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
162
            self.assertNotEqual(None, lockable._dir_mode)
 
163
            self.assertNotEqual(None, lockable._file_mode)
 
164
 
 
165
            LockableFiles._set_dir_mode = False
 
166
            transport = get_transport('.')
 
167
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
168
            self.assertEqual(None, lockable._dir_mode)
 
169
            self.assertNotEqual(None, lockable._file_mode)
 
170
 
 
171
            LockableFiles._set_file_mode = False
 
172
            transport = get_transport('.')
 
173
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
174
            self.assertEqual(None, lockable._dir_mode)
 
175
            self.assertEqual(None, lockable._file_mode)
 
176
 
 
177
            LockableFiles._set_dir_mode = True
 
178
            transport = get_transport('.')
 
179
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
180
            self.assertNotEqual(None, lockable._dir_mode)
 
181
            self.assertEqual(None, lockable._file_mode)
 
182
 
 
183
            LockableFiles._set_file_mode = True
 
184
            transport = get_transport('.')
 
185
            lockable = LockableFiles(transport, 'my-lock', TransportLock)
 
186
            self.assertNotEqual(None, lockable._dir_mode)
 
187
            self.assertNotEqual(None, lockable._file_mode)
 
188
        finally:
 
189
            LockableFiles._set_dir_mode = True
 
190
            LockableFiles._set_file_mode = True
 
191
 
169
192
 
170
193
class TestSftpPermissions(TestCaseWithSFTPServer):
171
194
 
177
200
 
178
201
        # bodge around for stubsftpserver not letting use connect
179
202
        # more than once
180
 
        _t = self.get_transport()
 
203
        _t = get_transport(self.get_url())
181
204
 
182
205
        os.mkdir('local')
183
206
        t_local = self.make_branch_and_tree('local')
184
207
        b_local = t_local.branch
185
 
        with open('local/a', 'wb') as f: f.write('foo\n')
 
208
        open('local/a', 'wb').write('foo\n')
186
209
        t_local.add('a')
187
210
        t_local.commit('foo')
188
211
 
194
217
        b_local = t.branch
195
218
        self.assertEqualMode(0755, b_local.control_files._dir_mode)
196
219
        self.assertEqualMode(0644, b_local.control_files._file_mode)
197
 
        self.assertEqualMode(0755, b_local.bzrdir._get_dir_mode())
198
 
        self.assertEqualMode(0644, b_local.bzrdir._get_file_mode())
199
220
 
200
221
        os.mkdir('sftp')
201
222
        sftp_url = self.get_url('sftp')
202
 
        b_sftp = ControlDir.create_branch_and_repo(sftp_url)
 
223
        b_sftp = BzrDir.create_branch_and_repo(sftp_url)
203
224
 
204
225
        b_sftp.pull(b_local)
205
226
        del b_sftp
209
230
        b_sftp = Branch.open(sftp_url)
210
231
        self.assertEqualMode(0755, b_sftp.control_files._dir_mode)
211
232
        self.assertEqualMode(0644, b_sftp.control_files._file_mode)
212
 
        self.assertEqualMode(0755, b_sftp.bzrdir._get_dir_mode())
213
 
        self.assertEqualMode(0644, b_sftp.bzrdir._get_file_mode())
214
233
 
215
 
        with open('local/a', 'wb') as f: f.write('foo2\n')
 
234
        open('local/a', 'wb').write('foo2\n')
216
235
        t_local.commit('foo2')
217
236
        b_sftp.pull(b_local)
218
237
        # The mode should be maintained after commit
219
238
        check_mode_r(self, 'sftp/.bzr', 0644, 0755)
220
239
 
221
 
        with open('local/b', 'wb') as f: f.write('new b\n')
 
240
        open('local/b', 'wb').write('new b\n')
222
241
        t_local.add('b')
223
242
        t_local.commit('new b')
224
243
        b_sftp.pull(b_local)
232
251
        b_sftp = Branch.open(sftp_url)
233
252
        self.assertEqualMode(0775, b_sftp.control_files._dir_mode)
234
253
        self.assertEqualMode(0664, b_sftp.control_files._file_mode)
235
 
        self.assertEqualMode(0775, b_sftp.bzrdir._get_dir_mode())
236
 
        self.assertEqualMode(0664, b_sftp.bzrdir._get_file_mode())
237
254
 
238
 
        with open('local/a', 'wb') as f: f.write('foo3\n')
 
255
        open('local/a', 'wb').write('foo3\n')
239
256
        t_local.commit('foo3')
240
257
        b_sftp.pull(b_local)
241
258
        check_mode_r(self, 'sftp/.bzr', 0664, 0775)
242
259
 
243
 
        with open('local/c', 'wb') as f: f.write('new c\n')
 
260
        open('local/c', 'wb').write('new c\n')
244
261
        t_local.add('c')
245
262
        t_local.commit('new c')
246
263
        b_sftp.pull(b_local)
254
271
        original_umask = os.umask(umask)
255
272
 
256
273
        try:
257
 
            t = self.get_transport()
 
274
            t = get_transport(self.get_url())
258
275
            # Direct access should be masked by umask
259
276
            t._sftp_open_exclusive('a', mode=0666).write('foo\n')
260
277
            self.assertTransportMode(t, 'a', 0666 &~umask)