/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/archive/zip.py

  • Committer: Jelmer Vernooij
  • Date: 2020-03-22 01:35:14 UTC
  • mfrom: (7490.7.6 work)
  • mto: This revision was merged to the branch mainline in revision 7499.
  • Revision ID: jelmer@jelmer.uk-20200322013514-7vw1ntwho04rcuj3
merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Export a Tree to a zip file.
18
18
"""
19
19
 
20
 
from __future__ import absolute_import
21
 
 
 
20
from contextlib import closing
22
21
import os
23
22
import stat
24
23
import sys
 
24
import tempfile
25
25
import time
26
26
import zipfile
27
27
 
42
42
_DIR_ATTR = stat.S_IFDIR | ZIP_DIRECTORY_BIT | DIR_PERMISSIONS
43
43
 
44
44
 
45
 
def zip_exporter_generator(tree, dest, root, subdir=None,
46
 
    force_mtime=None, fileobj=None):
 
45
def zip_archive_generator(tree, dest, root, subdir=None,
 
46
                          force_mtime=None):
47
47
    """ Export this tree to a new zip file.
48
48
 
49
49
    `dest` will be created holding the contents of this tree; if it
50
50
    already exists, it will be overwritten".
51
51
    """
52
 
 
53
52
    compression = zipfile.ZIP_DEFLATED
54
 
    if fileobj is not None:
55
 
        dest = fileobj
56
 
    elif dest == "-":
57
 
        dest = sys.stdout
58
 
    zipf = zipfile.ZipFile(dest, "w", compression)
59
 
    try:
60
 
        for dp, tp, ie in _export_iter_entries(tree, subdir):
61
 
            file_id = ie.file_id
62
 
            mutter("  export {%s} kind %s to %s", file_id, ie.kind, dest)
63
 
 
64
 
            # zipfile.ZipFile switches all paths to forward
65
 
            # slashes anyway, so just stick with that.
66
 
            if force_mtime is not None:
67
 
                mtime = force_mtime
68
 
            else:
69
 
                mtime = tree.get_file_mtime(tp, ie.file_id)
70
 
            date_time = time.localtime(mtime)[:6]
71
 
            filename = osutils.pathjoin(root, dp).encode('utf8')
72
 
            if ie.kind == "file":
73
 
                zinfo = zipfile.ZipInfo(
74
 
                            filename=filename,
75
 
                            date_time=date_time)
76
 
                zinfo.compress_type = compression
77
 
                zinfo.external_attr = _FILE_ATTR
78
 
                content = tree.get_file_text(tp, file_id)
79
 
                zipf.writestr(zinfo, content)
80
 
            elif ie.kind == "directory":
81
 
                # Directories must contain a trailing slash, to indicate
82
 
                # to the zip routine that they are really directories and
83
 
                # not just empty files.
84
 
                zinfo = zipfile.ZipInfo(
85
 
                            filename=filename + '/',
86
 
                            date_time=date_time)
87
 
                zinfo.compress_type = compression
88
 
                zinfo.external_attr = _DIR_ATTR
89
 
                zipf.writestr(zinfo, '')
90
 
            elif ie.kind == "symlink":
91
 
                zinfo = zipfile.ZipInfo(
92
 
                            filename=(filename + '.lnk'),
93
 
                            date_time=date_time)
94
 
                zinfo.compress_type = compression
95
 
                zinfo.external_attr = _FILE_ATTR
96
 
                zipf.writestr(zinfo, tree.get_symlink_target(tp, file_id))
97
 
            yield
98
 
 
99
 
        zipf.close()
100
 
 
101
 
    except UnicodeEncodeError:
102
 
        zipf.close()
103
 
        os.remove(dest)
104
 
        from breezy.errors import BzrError
105
 
        raise BzrError("Can't export non-ascii filenames to zip")
 
53
    with tempfile.SpooledTemporaryFile() as buf:
 
54
        with closing(zipfile.ZipFile(buf, "w", compression)) as zipf, \
 
55
                tree.lock_read():
 
56
            for dp, tp, ie in _export_iter_entries(tree, subdir):
 
57
                mutter("  export {%s} kind %s to %s", tp, ie.kind, dest)
 
58
 
 
59
                # zipfile.ZipFile switches all paths to forward
 
60
                # slashes anyway, so just stick with that.
 
61
                if force_mtime is not None:
 
62
                    mtime = force_mtime
 
63
                else:
 
64
                    mtime = tree.get_file_mtime(tp)
 
65
                date_time = time.localtime(mtime)[:6]
 
66
                filename = osutils.pathjoin(root, dp)
 
67
                if ie.kind == "file":
 
68
                    zinfo = zipfile.ZipInfo(
 
69
                        filename=filename,
 
70
                        date_time=date_time)
 
71
                    zinfo.compress_type = compression
 
72
                    zinfo.external_attr = _FILE_ATTR
 
73
                    content = tree.get_file_text(tp)
 
74
                    zipf.writestr(zinfo, content)
 
75
                elif ie.kind in ("directory", "tree-reference"):
 
76
                    # Directories must contain a trailing slash, to indicate
 
77
                    # to the zip routine that they are really directories and
 
78
                    # not just empty files.
 
79
                    zinfo = zipfile.ZipInfo(
 
80
                        filename=filename + '/',
 
81
                        date_time=date_time)
 
82
                    zinfo.compress_type = compression
 
83
                    zinfo.external_attr = _DIR_ATTR
 
84
                    zipf.writestr(zinfo, '')
 
85
                elif ie.kind == "symlink":
 
86
                    zinfo = zipfile.ZipInfo(
 
87
                        filename=(filename + '.lnk'),
 
88
                        date_time=date_time)
 
89
                    zinfo.compress_type = compression
 
90
                    zinfo.external_attr = _FILE_ATTR
 
91
                    zipf.writestr(zinfo, tree.get_symlink_target(tp))
 
92
        # Urgh, headers are written last since they include e.g. file size.
 
93
        # So we have to buffer it all :(
 
94
        buf.seek(0)
 
95
        for chunk in osutils.file_iterator(buf):
 
96
            yield chunk