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)
56
64
def make_readonly(filename):
57
65
"""Make a filename read-only."""
58
66
mod = os.stat(filename).st_mode
173
191
except IOError, e:
174
192
# RBC 20060103 abstraction leakage: the paramiko SFTP clients rename
175
# function raises an IOError with errno == None when a rename fails.
193
# function raises an IOError with errno is None when a rename fails.
176
194
# This then gets caught here.
177
195
if e.errno not in (None, errno.ENOENT, errno.ENOTDIR):
179
197
except Exception, e:
180
if (not hasattr(e, 'errno')
198
if (getattr(e, 'errno', None) is None
181
199
or e.errno not in (errno.ENOENT, errno.ENOTDIR)):
852
871
def supports_executable():
853
872
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
856
894
_validWin32PathRE = re.compile(r'^([A-Za-z]:[/\\])?[^:<>*"?\|]*$')
875
913
to exclude some directories, they are then not descended into.
877
915
The data yielded is of the form:
878
[(relpath, basename, kind, lstat, path_from_top), ...]
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.
880
931
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
881
932
allows one to walk a subtree but get paths that are relative to a tree
882
933
rooted higher up.
883
934
: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
887
943
_directory = _directory_kind
899
955
for name in sorted(_listdir(top)):
900
956
abspath = top + '/' + name
901
957
statvalue = lstat(abspath)
902
dirblock.append ((relroot + name, name, file_kind_from_stat_mode(statvalue.st_mode), statvalue, abspath))
958
dirblock.append((relroot + name, name,
959
file_kind_from_stat_mode(statvalue.st_mode),
961
yield (currentdir[0], top), dirblock
904
962
# push the user specified dirs from dirblock
905
963
for dir in reversed(dirblock):
906
964
if dir[2] == _directory:
907
965
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)
910
1010
def path_prefix_key(path):
911
1011
"""Generate a prefix-order path key for path.
920
1020
key_a = path_prefix_key(path_a)
921
1021
key_b = path_prefix_key(path_b)
922
1022
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 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