52
53
from bzrlib.trace import mutter
56
# On win32, O_BINARY is used to indicate the file should
57
# be opened in binary mode, rather than text mode.
58
# On other platforms, O_BINARY doesn't exist, because
59
# they always open in binary mode, so it is okay to
60
# OR with 0 on those platforms
61
O_BINARY = getattr(os, 'O_BINARY', 0)
55
64
def make_readonly(filename):
56
65
"""Make a filename read-only."""
57
66
mod = os.stat(filename).st_mode
215
234
return posixpath.realpath(path.encode(_fs_enc)).decode(_fs_enc)
237
def _win32_fixdrive(path):
238
"""Force drive letters to be consistent.
240
win32 is inconsistent whether it returns lower or upper case
241
and even if it was consistent the user might type the other
242
so we force it to uppercase
243
running python.exe under cmd.exe return capital C:\\
244
running win32 python inside a cygwin shell returns lowercase c:\\
246
drive, path = _nt_splitdrive(path)
247
return drive.upper() + path
218
250
def _win32_abspath(path):
219
251
# Real _nt_abspath doesn't have a problem with a unicode cwd
220
return _nt_abspath(unicode(path)).replace('\\', '/')
252
return _win32_fixdrive(_nt_abspath(unicode(path)).replace('\\', '/'))
223
255
def _win32_realpath(path):
224
256
# Real _nt_realpath doesn't have a problem with a unicode cwd
225
return _nt_realpath(unicode(path)).replace('\\', '/')
257
return _win32_fixdrive(_nt_realpath(unicode(path)).replace('\\', '/'))
228
260
def _win32_pathjoin(*args):
232
264
def _win32_normpath(path):
233
return _nt_normpath(unicode(path)).replace('\\', '/')
265
return _win32_fixdrive(_nt_normpath(unicode(path)).replace('\\', '/'))
236
268
def _win32_getcwd():
237
return os.getcwdu().replace('\\', '/')
269
return _win32_fixdrive(os.getcwdu().replace('\\', '/'))
240
272
def _win32_mkdtemp(*args, **kwargs):
241
return tempfile.mkdtemp(*args, **kwargs).replace('\\', '/')
273
return _win32_fixdrive(tempfile.mkdtemp(*args, **kwargs).replace('\\', '/'))
244
276
def _win32_rename(old, new):
245
fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
277
"""We expect to be able to atomically replace 'new' with old.
279
On win32, if new exists, it must be moved out of the way first,
283
fancy_rename(old, new, rename_func=os.rename, unlink_func=os.unlink)
285
if e.errno in (errno.EPERM, errno.EACCES, errno.EBUSY, errno.EINVAL):
286
# If we try to rename a non-existant file onto cwd, we get
287
# EPERM or EACCES instead of ENOENT, this will raise ENOENT
288
# if the old path doesn't exist, sometimes we get EACCES
289
# On Linux, we seem to get EBUSY, on Mac we get EINVAL
295
return unicodedata.normalize('NFKC', os.getcwdu())
248
298
# Default is to just use the python builtins, but these can be rebound on
761
813
return _platform_normalizes_filenames
816
def _accessible_normalized_filename(path):
817
"""Get the unicode normalized path, and if you can access the file.
819
On platforms where the system normalizes filenames (Mac OSX),
820
you can access a file by any path which will normalize correctly.
821
On platforms where the system does not normalize filenames
822
(Windows, Linux), you have to access a file by its exact path.
824
Internally, bzr only supports NFC/NFKC normalization, since that is
825
the standard for XML documents.
827
So return the normalized path, and a flag indicating if the file
828
can be accessed by that path.
831
return unicodedata.normalize('NFKC', unicode(path)), True
834
def _inaccessible_normalized_filename(path):
835
__doc__ = _accessible_normalized_filename.__doc__
837
normalized = unicodedata.normalize('NFKC', unicode(path))
838
return normalized, normalized == path
764
841
if _platform_normalizes_filenames:
765
def unicode_filename(path):
766
"""Make sure 'path' is a properly normalized filename.
768
On platforms where the system normalizes filenames (Mac OSX),
769
you can access a file by any path which will normalize
771
Internally, bzr only supports NFC/NFKC normalization, since
772
that is the standard for XML documents.
773
So we return an normalized path, and indicate this has been
776
:return: (path, is_normalized) Return a path which can
777
access the file, and whether or not this path is
780
return unicodedata.normalize('NFKC', path), True
842
normalized_filename = _accessible_normalized_filename
782
def unicode_filename(path):
783
"""Make sure 'path' is a properly normalized filename.
785
On platforms where the system does not normalize filenames
786
(Windows, Linux), you have to access a file by its exact path.
787
Internally, bzr only supports NFC/NFKC normalization, since
788
that is the standard for XML documents.
789
So we return the original path, and indicate if this is
792
:return: (path, is_normalized) Return a path which can
793
access the file, and whether or not this path is
796
return path, unicodedata.normalize('NFKC', path) == path
844
normalized_filename = _inaccessible_normalized_filename
799
847
def terminal_width():
845
893
to exclude some directories, they are then not descended into.
847
895
The data yielded is of the form:
848
[(relpath, basename, kind, lstat, path_from_top), ...]
896
((directory-relpath, directory-path-from-top),
897
[(relpath, basename, kind, lstat), ...]),
898
- directory-relpath is the relative path of the directory being returned
899
with respect to top. prefix is prepended to this.
900
- directory-path-from-root is the path including top for this directory.
901
It is suitable for use with os functions.
902
- relpath is the relative path within the subtree being walked.
903
- basename is the basename of the path
904
- kind is the kind of the file now. If unknown then the file is not
905
present within the tree - but it may be recorded as versioned. See
907
- lstat is the stat data *if* the file was statted.
908
- planned, not implemented:
909
path_from_tree_root is the path from the root of the tree.
850
911
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
851
912
allows one to walk a subtree but get paths that are relative to a tree
852
913
rooted higher up.
853
914
:return: an iterator over the dirs.
916
#TODO there is a bit of a smell where the results of the directory-
917
# summary in this, and the path from the root, may not agree
918
# depending on top and prefix - i.e. ./foo and foo as a pair leads to
919
# potentially confusing output. We should make this more robust - but
920
# not at a speed cost. RBC 20060731
857
923
_directory = _directory_kind
869
935
for name in sorted(_listdir(top)):
870
936
abspath = top + '/' + name
871
937
statvalue = lstat(abspath)
872
dirblock.append ((relroot + name, name, file_kind_from_stat_mode(statvalue.st_mode), statvalue, abspath))
938
dirblock.append((relroot + name, name,
939
file_kind_from_stat_mode(statvalue.st_mode),
941
yield (currentdir[0], top), dirblock
874
942
# push the user specified dirs from dirblock
875
943
for dir in reversed(dirblock):
876
944
if dir[2] == _directory:
877
945
pending.append(dir)
948
def copy_tree(from_path, to_path, handlers={}):
949
"""Copy all of the entries in from_path into to_path.
951
:param from_path: The base directory to copy.
952
:param to_path: The target directory. If it does not exist, it will
954
:param handlers: A dictionary of functions, which takes a source and
955
destinations for files, directories, etc.
956
It is keyed on the file kind, such as 'directory', 'symlink', or 'file'
957
'file', 'directory', and 'symlink' should always exist.
958
If they are missing, they will be replaced with 'os.mkdir()',
959
'os.readlink() + os.symlink()', and 'shutil.copy2()', respectively.
961
# Now, just copy the existing cached tree to the new location
962
# We use a cheap trick here.
963
# Absolute paths are prefixed with the first parameter
964
# relative paths are prefixed with the second.
965
# So we can get both the source and target returned
966
# without any extra work.
968
def copy_dir(source, dest):
971
def copy_link(source, dest):
972
"""Copy the contents of a symlink"""
973
link_to = os.readlink(source)
974
os.symlink(link_to, dest)
976
real_handlers = {'file':shutil.copy2,
978
'directory':copy_dir,
980
real_handlers.update(handlers)
982
if not os.path.exists(to_path):
983
real_handlers['directory'](from_path, to_path)
985
for dir_info, entries in walkdirs(from_path, prefix=to_path):
986
for relpath, name, kind, st, abspath in entries:
987
real_handlers[kind](abspath, relpath)
880
990
def path_prefix_key(path):
881
991
"""Generate a prefix-order path key for path.