~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/local.py

Update non_atomic_put to have a create_parent_dir flag

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
This is a fairly thin wrapper on regular file IO.
20
20
"""
21
21
 
 
22
import errno
22
23
import os
23
24
import shutil
24
25
import sys
154
155
        finally:
155
156
            fp.close()
156
157
 
157
 
    def non_atomic_put(self, relpath, f, mode=None):
 
158
    def non_atomic_put(self, relpath, f, mode=None, create_parent_dir=False):
158
159
        """Copy the file-like object into the target location.
159
160
 
160
161
        This function is not strictly safe to use. It is only meant to
166
167
        :param f:       File-like object.
167
168
        :param mode:    Possible access permissions for new file.
168
169
                        None means do not set remote permissions.
 
170
        :param create_parent_dir: If we cannot create the target file because
 
171
                        the parent directory does not exist, go ahead and
 
172
                        create it, and then try again.
169
173
        """
170
174
        abspath = self._abspath(relpath)
171
175
        if mode is None:
176
180
        try:
177
181
            fd = os.open(abspath, _non_atomic_put_flags, local_mode)
178
182
        except (IOError, OSError),e:
179
 
            self._translate_error(e, relpath)
 
183
            # We couldn't create the file, maybe we need to create
 
184
            # the parent directory, and try again
 
185
            if (not create_parent_dir
 
186
                or e.errno not in (errno.ENOENT,errno.ENOTDIR)):
 
187
                self._translate_error(e, relpath)
 
188
            parent_dir = os.path.dirname(abspath)
 
189
            if not parent_dir:
 
190
                self._translate_error(e, relpath)
 
191
            try:
 
192
                os.mkdir(parent_dir)
 
193
            except (IOError, OSError), e:
 
194
                self._translate_error(e, relpath)
 
195
            # We created the parent directory, lets try to open the
 
196
            # file again
 
197
            try:
 
198
                fd = os.open(abspath, _non_atomic_put_flags, local_mode)
 
199
            except (IOError, OSError), e:
 
200
                self._translate_error(e, relpath)
180
201
        try:
181
202
            st = os.fstat(fd)
182
203
            if mode is not None and mode != S_IMODE(st.st_mode):