53
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)
64
56
def make_readonly(filename):
65
57
"""Make a filename read-only."""
66
58
mod = os.stat(filename).st_mode
191
173
except IOError, e:
192
174
# RBC 20060103 abstraction leakage: the paramiko SFTP clients rename
193
# function raises an IOError with errno is None when a rename fails.
175
# function raises an IOError with errno == None when a rename fails.
194
176
# This then gets caught here.
195
177
if e.errno not in (None, errno.ENOENT, errno.ENOTDIR):
197
179
except Exception, e:
198
if (getattr(e, 'errno', None) is None
180
if (not hasattr(e, 'errno')
199
181
or e.errno not in (errno.ENOENT, errno.ENOTDIR)):
871
852
def supports_executable():
872
853
return sys.platform != "win32"
875
def set_or_unset_env(env_variable, value):
876
"""Modify the environment, setting or removing the env_variable.
878
:param env_variable: The environment variable in question
879
:param value: The value to set the environment to. If None, then
880
the variable will be removed.
881
:return: The original value of the environment variable.
883
orig_val = os.environ.get(env_variable)
885
if orig_val is not None:
886
del os.environ[env_variable]
888
if isinstance(value, unicode):
889
value = value.encode(bzrlib.user_encoding)
890
os.environ[env_variable] = value
894
856
_validWin32PathRE = re.compile(r'^([A-Za-z]:[/\\])?[^:<>*"?\|]*$')
913
875
to exclude some directories, they are then not descended into.
915
877
The data yielded is of the form:
916
((directory-relpath, directory-path-from-top),
917
[(relpath, basename, kind, lstat), ...]),
918
- directory-relpath is the relative path of the directory being returned
919
with respect to top. prefix is prepended to this.
920
- directory-path-from-root is the path including top for this directory.
921
It is suitable for use with os functions.
922
- relpath is the relative path within the subtree being walked.
923
- basename is the basename of the path
924
- kind is the kind of the file now. If unknown then the file is not
925
present within the tree - but it may be recorded as versioned. See
927
- lstat is the stat data *if* the file was statted.
928
- planned, not implemented:
929
path_from_tree_root is the path from the root of the tree.
878
[(relpath, basename, kind, lstat, path_from_top), ...]
931
880
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
932
881
allows one to walk a subtree but get paths that are relative to a tree
933
882
rooted higher up.
934
883
:return: an iterator over the dirs.
936
#TODO there is a bit of a smell where the results of the directory-
937
# summary in this, and the path from the root, may not agree
938
# depending on top and prefix - i.e. ./foo and foo as a pair leads to
939
# potentially confusing output. We should make this more robust - but
940
# not at a speed cost. RBC 20060731
943
887
_directory = _directory_kind
955
899
for name in sorted(_listdir(top)):
956
900
abspath = top + '/' + name
957
901
statvalue = lstat(abspath)
958
dirblock.append((relroot + name, name,
959
file_kind_from_stat_mode(statvalue.st_mode),
961
yield (currentdir[0], top), dirblock
902
dirblock.append ((relroot + name, name, file_kind_from_stat_mode(statvalue.st_mode), statvalue, abspath))
962
904
# push the user specified dirs from dirblock
963
905
for dir in reversed(dirblock):
964
906
if dir[2] == _directory:
965
907
pending.append(dir)
968
def copy_tree(from_path, to_path, handlers={}):
969
"""Copy all of the entries in from_path into to_path.
971
:param from_path: The base directory to copy.
972
:param to_path: The target directory. If it does not exist, it will
974
:param handlers: A dictionary of functions, which takes a source and
975
destinations for files, directories, etc.
976
It is keyed on the file kind, such as 'directory', 'symlink', or 'file'
977
'file', 'directory', and 'symlink' should always exist.
978
If they are missing, they will be replaced with 'os.mkdir()',
979
'os.readlink() + os.symlink()', and 'shutil.copy2()', respectively.
981
# Now, just copy the existing cached tree to the new location
982
# We use a cheap trick here.
983
# Absolute paths are prefixed with the first parameter
984
# relative paths are prefixed with the second.
985
# So we can get both the source and target returned
986
# without any extra work.
988
def copy_dir(source, dest):
991
def copy_link(source, dest):
992
"""Copy the contents of a symlink"""
993
link_to = os.readlink(source)
994
os.symlink(link_to, dest)
996
real_handlers = {'file':shutil.copy2,
998
'directory':copy_dir,
1000
real_handlers.update(handlers)
1002
if not os.path.exists(to_path):
1003
real_handlers['directory'](from_path, to_path)
1005
for dir_info, entries in walkdirs(from_path, prefix=to_path):
1006
for relpath, name, kind, st, abspath in entries:
1007
real_handlers[kind](abspath, relpath)
1010
910
def path_prefix_key(path):
1011
911
"""Generate a prefix-order path key for path.
1020
920
key_a = path_prefix_key(path_a)
1021
921
key_b = path_prefix_key(path_b)
1022
922
return cmp(key_a, key_b)
1025
_cached_user_encoding = None
1028
def get_user_encoding():
1029
"""Find out what the preferred user encoding is.
1031
This is generally the encoding that is used for command line parameters
1032
and file contents. This may be different from the terminal encoding
1033
or the filesystem encoding.
1035
:return: A string defining the preferred user encoding
1037
global _cached_user_encoding
1038
if _cached_user_encoding is not None:
1039
return _cached_user_encoding
1041
if sys.platform == 'darwin':
1042
# work around egregious python 2.4 bug
1043
sys.platform = 'posix'
1047
sys.platform = 'darwin'
1052
_cached_user_encoding = locale.getpreferredencoding()
1053
except locale.Error, e:
1054
sys.stderr.write('bzr: warning: %s\n'
1055
' Could not determine what text encoding to use.\n'
1056
' This error usually means your Python interpreter\n'
1057
' doesn\'t support the locale set by $LANG (%s)\n'
1058
" Continuing with ascii encoding.\n"
1059
% (e, os.environ.get('LANG')))
1061
if _cached_user_encoding is None:
1062
_cached_user_encoding = 'ascii'
1063
return _cached_user_encoding