52
54
compression = zipfile.ZIP_DEFLATED
53
55
with tempfile.SpooledTemporaryFile() as buf:
54
56
with closing(zipfile.ZipFile(buf, "w", compression)) as zipf, \
56
58
for dp, tp, ie in _export_iter_entries(tree, subdir):
57
mutter(" export {%s} kind %s to %s", tp, ie.kind, dest)
59
file_id = getattr(ie, 'file_id', None)
60
mutter(" export {%s} kind %s to %s", file_id, ie.kind, dest)
59
62
# zipfile.ZipFile switches all paths to forward
60
63
# slashes anyway, so just stick with that.
61
64
if force_mtime is not None:
62
65
mtime = force_mtime
64
mtime = tree.get_file_mtime(tp)
67
mtime = tree.get_file_mtime(tp, file_id)
65
68
date_time = time.localtime(mtime)[:6]
66
filename = osutils.pathjoin(root, dp)
69
filename = osutils.pathjoin(root, dp).encode('utf8')
67
70
if ie.kind == "file":
68
71
zinfo = zipfile.ZipInfo(
71
74
zinfo.compress_type = compression
72
75
zinfo.external_attr = _FILE_ATTR
73
content = tree.get_file_text(tp)
76
content = tree.get_file_text(tp, file_id)
74
77
zipf.writestr(zinfo, content)
75
78
elif ie.kind in ("directory", "tree-reference"):
76
79
# Directories must contain a trailing slash, to indicate
77
80
# to the zip routine that they are really directories and
78
81
# not just empty files.
79
82
zinfo = zipfile.ZipInfo(
80
filename=filename + '/',
83
filename=filename + '/',
82
85
zinfo.compress_type = compression
83
86
zinfo.external_attr = _DIR_ATTR
84
87
zipf.writestr(zinfo, '')
85
88
elif ie.kind == "symlink":
86
89
zinfo = zipfile.ZipInfo(
87
filename=(filename + '.lnk'),
90
filename=(filename + '.lnk'),
89
92
zinfo.compress_type = compression
90
93
zinfo.external_attr = _FILE_ATTR
91
zipf.writestr(zinfo, tree.get_symlink_target(tp))
94
zipf.writestr(zinfo, tree.get_symlink_target(tp, file_id))
92
95
# Urgh, headers are written last since they include e.g. file size.
93
96
# So we have to buffer it all :(