110
113
raise BzrError("lstat/stat of (%r): %r" % (f, e))
112
def normalizepath(f):
113
if hasattr(os.path, 'realpath'):
117
[p,e] = os.path.split(f)
118
if e == "" or e == "." or e == "..":
121
return os.path.join(F(p), e)
115
def fancy_rename(old, new, rename_func, unlink_func):
116
"""A fancy rename, when you don't have atomic rename.
118
:param old: The old path, to rename from
119
:param new: The new path, to rename to
120
:param rename_func: The potentially non-atomic rename function
121
:param unlink_func: A way to delete the target file if the full rename succeeds
124
# sftp rename doesn't allow overwriting, so play tricks:
126
base = os.path.basename(new)
127
dirname = os.path.dirname(new)
128
tmp_name = u'tmp.%s.%.9f.%d.%d' % (base, time.time(), os.getpid(), random.randint(0, 0x7FFFFFFF))
129
tmp_name = pathjoin(dirname, tmp_name)
131
# Rename the file out of the way, but keep track if it didn't exist
132
# We don't want to grab just any exception
133
# something like EACCES should prevent us from continuing
134
# The downside is that the rename_func has to throw an exception
135
# with an errno = ENOENT, or NoSuchFile
138
rename_func(new, tmp_name)
139
except (NoSuchFile,), e:
142
if (not hasattr(e, 'errno')
143
or e.errno not in (errno.ENOENT, errno.ENOTDIR)):
150
# This may throw an exception, in which case success will
152
rename_func(old, new)
156
# If the file used to exist, rename it back into place
157
# otherwise just delete it from the tmp location
159
unlink_func(tmp_name)
161
rename_func(tmp_name, new)
163
# Default is to just use the python builtins
164
abspath = os.path.abspath
165
realpath = os.path.realpath
166
pathjoin = os.path.join
167
normpath = os.path.normpath
169
mkdtemp = tempfile.mkdtemp
171
dirname = os.path.dirname
172
basename = os.path.basename
123
174
if os.name == "posix":
124
175
# In Python 2.4.2 and older, os.path.abspath and os.path.realpath
128
179
_fs_enc = sys.getfilesystemencoding()
129
180
def abspath(path):
130
181
return os.path.abspath(path.encode(_fs_enc)).decode(_fs_enc)
131
183
def realpath(path):
132
184
return os.path.realpath(path.encode(_fs_enc)).decode(_fs_enc)
186
if sys.platform == 'win32':
134
187
# We need to use the Unicode-aware os.path.abspath and
135
188
# os.path.realpath on Windows systems.
136
abspath = os.path.abspath
137
realpath = os.path.realpath
190
return os.path.abspath(path).replace('\\', '/')
193
return os.path.realpath(path).replace('\\', '/')
196
return os.path.join(*args).replace('\\', '/')
199
return os.path.normpath(path).replace('\\', '/')
202
return os.getcwdu().replace('\\', '/')
204
def mkdtemp(*args, **kwargs):
205
return tempfile.mkdtemp(*args, **kwargs).replace('\\', '/')
207
def rename(old, new):
208
fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
210
def normalizepath(f):
211
if hasattr(os.path, 'realpath'):
215
[p,e] = os.path.split(f)
216
if e == "" or e == "." or e == "..":
219
return pathjoin(F(p), e)
139
222
def backup_file(fn):
140
223
"""Copy a file to a backup.
195
272
def is_inside(dir, fname):
196
273
"""True if fname is inside dir.
198
The parameters should typically be passed to os.path.normpath first, so
275
The parameters should typically be passed to osutils.normpath first, so
199
276
that . and .. and repeated slashes are eliminated, and the separators
200
277
are canonical for the platform.
202
279
The empty string as a dir name is taken as top-of-tree and matches
205
>>> is_inside('src', os.path.join('src', 'foo.c'))
282
>>> is_inside('src', pathjoin('src', 'foo.c'))
207
284
>>> is_inside('src', 'srccontrol')
209
>>> is_inside('src', os.path.join('src', 'a', 'a', 'a', 'foo.c'))
286
>>> is_inside('src', pathjoin('src', 'a', 'a', 'a', 'foo.c'))
211
288
>>> is_inside('foo.c', 'foo.c')