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
875
893
to exclude some directories, they are then not descended into.
877
895
The data yielded is of the form:
878
[(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.
880
911
:param prefix: Prefix the relpaths that are yielded with 'prefix'. This
881
912
allows one to walk a subtree but get paths that are relative to a tree
882
913
rooted higher up.
883
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
887
923
_directory = _directory_kind
899
935
for name in sorted(_listdir(top)):
900
936
abspath = top + '/' + name
901
937
statvalue = lstat(abspath)
902
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
904
942
# push the user specified dirs from dirblock
905
943
for dir in reversed(dirblock):
906
944
if dir[2] == _directory:
907
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)
910
990
def path_prefix_key(path):
911
991
"""Generate a prefix-order path key for path.