1079
1079
# depending on top and prefix - i.e. ./foo and foo as a pair leads to
1080
1080
# potentially confusing output. We should make this more robust - but
1081
1081
# not at a speed cost. RBC 20060731
1084
1083
_directory = _directory_kind
1085
1084
_listdir = os.listdir
1086
pending = [(prefix, "", _directory, None, top)]
1085
_kind_from_mode = _formats.get
1086
pending = [(safe_unicode(prefix), "", _directory, None, safe_unicode(top))]
1089
currentdir = pending.pop()
1090
1088
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1093
relroot = currentdir[0] + '/'
1096
for name in sorted(_listdir(top)):
1097
abspath = top + '/' + name
1098
statvalue = lstat(abspath)
1099
dirblock.append((relroot + name, name,
1100
file_kind_from_stat_mode(statvalue.st_mode),
1101
statvalue, abspath))
1102
yield (currentdir[0], top), dirblock
1103
# push the user specified dirs from dirblock
1104
for dir in reversed(dirblock):
1105
if dir[2] == _directory:
1089
relroot, _, _, _, top = pending.pop()
1091
relprefix = relroot + u'/'
1094
top_slash = top + u'/'
1097
append = dirblock.append
1098
for name in sorted(_listdir(top)):
1099
abspath = top_slash + name
1100
statvalue = _lstat(abspath)
1101
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1102
append((relprefix + name, name, kind, statvalue, abspath))
1103
yield (relroot, top), dirblock
1105
# push the user specified dirs from dirblock
1106
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1109
def _walkdirs_utf8(top, prefix=""):
1110
"""Yield data about all the directories in a tree.
1112
This yields the same information as walkdirs() only each entry is yielded
1113
in utf-8. On platforms which have a filesystem encoding of utf8 the paths
1114
are returned as exact byte-strings.
1116
:return: yields a tuple of (dir_info, [file_info])
1117
dir_info is (utf8_relpath, path-from-top)
1118
file_info is (utf8_relpath, utf8_name, kind, lstat, path-from-top)
1119
if top is an absolute path, path-from-top is also an absolute path.
1120
path-from-top might be unicode or utf8, but it is the correct path to
1121
pass to os functions to affect the file in question. (such as os.lstat)
1123
fs_encoding = sys.getfilesystemencoding()
1124
if (sys.platform == 'win32' or
1125
fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
1126
return _walkdirs_unicode_to_utf8(top, prefix=prefix)
1128
return _walkdirs_fs_utf8(top, prefix=prefix)
1131
def _walkdirs_fs_utf8(top, prefix=""):
1132
"""See _walkdirs_utf8.
1134
This sub-function is called when we know the filesystem is already in utf8
1135
encoding. So we don't need to transcode filenames.
1138
_directory = _directory_kind
1139
_listdir = os.listdir
1140
_kind_from_mode = _formats.get
1142
# 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath
1143
# But we don't actually uses 1-3 in pending, so set them to None
1144
pending = [(safe_utf8(prefix), None, None, None, safe_utf8(top))]
1146
relroot, _, _, _, top = pending.pop()
1148
relprefix = relroot + '/'
1151
top_slash = top + '/'
1154
append = dirblock.append
1155
for name in sorted(_listdir(top)):
1156
abspath = top_slash + name
1157
statvalue = _lstat(abspath)
1158
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1159
append((relprefix + name, name, kind, statvalue, abspath))
1160
yield (relroot, top), dirblock
1162
# push the user specified dirs from dirblock
1163
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1166
def _walkdirs_unicode_to_utf8(top, prefix=""):
1167
"""See _walkdirs_utf8
1169
Because Win32 has a Unicode api, all of the 'path-from-top' entries will be
1171
This is currently the fallback code path when the filesystem encoding is
1172
not UTF-8. It may be better to implement an alternative so that we can
1173
safely handle paths that are not properly decodable in the current
1176
_utf8_encode = codecs.getencoder('utf8')
1178
_directory = _directory_kind
1179
_listdir = os.listdir
1180
_kind_from_mode = _formats.get
1182
pending = [(safe_utf8(prefix), None, None, None, safe_unicode(top))]
1184
relroot, _, _, _, top = pending.pop()
1186
relprefix = relroot + '/'
1189
top_slash = top + u'/'
1192
append = dirblock.append
1193
for name in sorted(_listdir(top)):
1194
name_utf8 = _utf8_encode(name)[0]
1195
abspath = top_slash + name
1196
statvalue = _lstat(abspath)
1197
kind = _kind_from_mode(statvalue.st_mode & 0170000, 'unknown')
1198
append((relprefix + name_utf8, name_utf8, kind, statvalue, abspath))
1199
yield (relroot, top), dirblock
1201
# push the user specified dirs from dirblock
1202
pending.extend(d for d in reversed(dirblock) if d[2] == _directory)
1109
1205
def copy_tree(from_path, to_path, handlers={}):