~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/lockable_files.py

MergeĀ fromĀ jam-storage.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
    _lock_mode = None
23
23
    _lock_count = None
24
24
    _lock = None
 
25
    # If set to False (by a plugin, etc) BzrBranch will not set the
 
26
    # mode on created files or directories
 
27
    _set_file_mode = True
 
28
    _set_dir_mode = True
25
29
 
26
 
    def __init__(self, transport, base, lock_name):
 
30
    def __init__(self, transport, lock_name):
27
31
        object.__init__(self)
28
32
        self._transport = transport
29
 
        self.base = base
30
33
        self.lock_name = lock_name
31
34
        self._transaction = None
 
35
        self._find_modes()
32
36
 
33
37
    def __del__(self):
34
38
        if self._lock_mode or self._lock:
38
42
            warn("file group %r was not explicitly unlocked" % self)
39
43
            self._lock.unlock()
40
44
 
41
 
    def _rel_controlfilename(self, file_or_path):
 
45
    def _escape(self, file_or_path):
42
46
        if not isinstance(file_or_path, basestring):
43
47
            file_or_path = '/'.join(file_or_path)
44
48
        if file_or_path == '':
45
 
            return unicode(self.base)
46
 
        return bzrlib.transport.urlescape(unicode(self.base + '/' + 
47
 
                                                  file_or_path))
 
49
            return u''
 
50
        return bzrlib.transport.urlescape(unicode(file_or_path))
 
51
 
 
52
    def _find_modes(self):
 
53
        """Determine the appropriate modes for files and directories."""
 
54
        try:
 
55
            try:
 
56
                st = self._transport.stat(u'.')
 
57
            except errors.NoSuchFile:
 
58
                # The .bzr/ directory doesn't exist, try to
 
59
                # inherit the permissions from the parent directory
 
60
                # but only try 1 level up
 
61
                temp_transport = self._transport.clone('..')
 
62
                st = temp_transport.stat(u'.')
 
63
        except (errors.TransportNotPossible, errors.NoSuchFile):
 
64
            self._dir_mode = 0755
 
65
            self._file_mode = 0644
 
66
        else:
 
67
            self._dir_mode = st.st_mode & 07777
 
68
            # Remove the sticky and execute bits for files
 
69
            self._file_mode = self._dir_mode & ~07111
 
70
        if not self._set_dir_mode:
 
71
            self._dir_mode = None
 
72
        if not self._set_file_mode:
 
73
            self._file_mode = None
48
74
 
49
75
    def controlfilename(self, file_or_path):
50
76
        """Return location relative to branch."""
51
 
        return self._transport.abspath(self._rel_controlfilename(file_or_path))
 
77
        return self._transport.abspath(self._escape(file_or_path))
52
78
 
53
79
    def controlfile(self, file_or_path, mode='r'):
54
80
        """Open a control file for this branch.
63
89
        """
64
90
        import codecs
65
91
 
66
 
        relpath = self._rel_controlfilename(file_or_path)
 
92
        relpath = self._escape(file_or_path)
67
93
        #TODO: codecs.open() buffers linewise, so it was overloaded with
68
94
        # a much larger buffer, do we need to do the same for getreader/getwriter?
69
95
        if mode == 'rb': 
90
116
        """
91
117
        if not self._lock_mode == 'w':
92
118
            raise ReadOnlyError()
93
 
        self._transport.put(self._rel_controlfilename(path), file)
 
119
        self._transport.put(self._escape(path), file, mode=self._file_mode)
94
120
 
95
121
    def put_utf8(self, path, file, mode=None):
96
122
        """Write a file, encoding as utf-8.
110
136
        # instead of files.  ADHB 2005-12-25
111
137
        # RBC 20060103 surely its not needed anyway, with codecs transcode
112
138
        # file support ?
113
 
        encoded_file = IterableFile(b.encode('utf-8', 'replace') for b in 
 
139
        # JAM 20060103 We definitely don't want encode(..., 'replace')
 
140
        # these are valuable files which should have exact contents.
 
141
        encoded_file = IterableFile(b.encode('utf-8') for b in 
114
142
                                    iterator)
115
143
        self.put(path, encoded_file)
116
144
 
125
153
            self._lock_count += 1
126
154
        else:
127
155
            self._lock = self._transport.lock_write(
128
 
                    self._rel_controlfilename(self.lock_name))
 
156
                    self._escape(self.lock_name))
129
157
            self._lock_mode = 'w'
130
158
            self._lock_count = 1
131
159
            self._set_transaction(transactions.PassThroughTransaction())
138
166
            self._lock_count += 1
139
167
        else:
140
168
            self._lock = self._transport.lock_read(
141
 
                    self._rel_controlfilename(self.lock_name))
 
169
                    self._escape(self.lock_name))
142
170
            self._lock_mode = 'r'
143
171
            self._lock_count = 1
144
172
            self._set_transaction(transactions.ReadOnlyTransaction())