/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-07-18 23:14:00 UTC
  • mfrom: (7490.40.62 work)
  • mto: This revision was merged to the branch mainline in revision 7519.
  • Revision ID: jelmer@jelmer.uk-20200718231400-jaes9qltn8oi8xss
Merge lp:brz/3.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2008, 2009, 2010 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Export a Tree to a zip file.
 
18
"""
 
19
 
 
20
from contextlib import closing
 
21
import os
 
22
import stat
 
23
import sys
 
24
import tempfile
 
25
import time
 
26
import zipfile
 
27
 
 
28
from .. import (
 
29
    osutils,
 
30
    )
 
31
from ..export import _export_iter_entries
 
32
from ..trace import mutter
 
33
 
 
34
 
 
35
# Windows expects this bit to be set in the 'external_attr' section,
 
36
# or it won't consider the entry a directory.
 
37
ZIP_DIRECTORY_BIT = (1 << 4)
 
38
FILE_PERMISSIONS = (0o644 << 16)
 
39
DIR_PERMISSIONS = (0o755 << 16)
 
40
 
 
41
_FILE_ATTR = stat.S_IFREG | FILE_PERMISSIONS
 
42
_DIR_ATTR = stat.S_IFDIR | ZIP_DIRECTORY_BIT | DIR_PERMISSIONS
 
43
 
 
44
 
 
45
def zip_archive_generator(tree, dest, root, subdir=None,
 
46
                          force_mtime=None):
 
47
    """ Export this tree to a new zip file.
 
48
 
 
49
    `dest` will be created holding the contents of this tree; if it
 
50
    already exists, it will be overwritten".
 
51
    """
 
52
    compression = zipfile.ZIP_DEFLATED
 
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