/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5724.1.3 by John Arbash Meinel
Change the exporters to ensure that we are writing the data out in binary mode.
1
# Copyright (C) 2005, 2006, 2008-2011 Canonical Ltd
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
2
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
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.
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
7
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
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.
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
12
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
16
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
17
"""Export a tree to a tarball."""
18
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
19
from contextlib import closing
7479.2.1 by Jelmer Vernooij
Drop python2 support.
20
from io import BytesIO
5718.5.15 by Jelmer Vernooij
Only write out basename of the tarfile to the gzip file.
21
import os
3368.2.32 by Ian Clatworthy
add --filters to export command
22
import sys
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
23
import tarfile
3408.7.1 by Martin Pool
Support tarball export to stdout
24
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
25
from .. import (
5718.1.1 by Jelmer Vernooij
Fix import of BzrError.
26
    errors,
27
    osutils,
28
    )
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
29
from ..export import _export_iter_entries
5718.5.2 by Jelmer Vernooij
Factor out export_tarball.
30
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
31
6331.2.1 by Jelmer Vernooij
Consistently pass tree path when exporting.
32
def prepare_tarball_item(tree, root, final_path, tree_path, entry, force_mtime=None):
5952.1.17 by geoffreyfishing at gmail
Renamed export item function in tar exporter.
33
    """Prepare a tarball item for exporting
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
34
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
35
    :param tree: Tree to export
5952.1.14 by geoffreyfishing at gmail
Cleaned up code and removed unnecessary arguments.
36
    :param final_path: Final path to place item
6331.2.1 by Jelmer Vernooij
Consistently pass tree path when exporting.
37
    :param tree_path: Path for the entry in the tree
5952.1.14 by geoffreyfishing at gmail
Cleaned up code and removed unnecessary arguments.
38
    :param entry: Entry to export
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
39
    :param force_mtime: Option mtime to force, instead of using tree
40
        timestamps.
41
5952.1.17 by geoffreyfishing at gmail
Renamed export item function in tar exporter.
42
    Returns a (tarinfo, fileobj) tuple
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
43
    """
6973.3.4 by Jelmer Vernooij
Don't assume entries returned by trees have a 'file_id' attribute.
44
    file_id = getattr(entry, 'file_id', None)
7007.1.13 by Jelmer Vernooij
Fix regression in tar handling.
45
    filename = osutils.pathjoin(root, final_path)
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
46
    item = tarfile.TarInfo(filename)
47
    if force_mtime is not None:
48
        item.mtime = force_mtime
49
    else:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
50
        item.mtime = tree.get_file_mtime(tree_path)
5952.1.14 by geoffreyfishing at gmail
Cleaned up code and removed unnecessary arguments.
51
    if entry.kind == "file":
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
52
        item.type = tarfile.REGTYPE
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
53
        if tree.is_executable(tree_path):
6619.3.17 by Jelmer Vernooij
Run 2to3 numliterals fixer.
54
            item.mode = 0o755
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
55
        else:
6619.3.17 by Jelmer Vernooij
Run 2to3 numliterals fixer.
56
            item.mode = 0o644
6006.3.4 by Martin Pool
Support exporting tarballs from ContentFilterTree
57
        # This brings the whole file into memory, but that's almost needed for
58
        # the tarfile contract, which wants the size of the file up front.  We
59
        # want to make sure it doesn't change, and we need to read it in one
60
        # go for content filtering.
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
61
        content = tree.get_file_text(tree_path)
6006.3.4 by Martin Pool
Support exporting tarballs from ContentFilterTree
62
        item.size = len(content)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
63
        fileobj = BytesIO(content)
6964.1.1 by Jelmer Vernooij
Support exporting nested trees.
64
    elif entry.kind in ("directory", "tree-reference"):
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
65
        item.type = tarfile.DIRTYPE
66
        item.name += '/'
67
        item.size = 0
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
68
        item.mode = 0o755
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
69
        fileobj = None
5952.1.14 by geoffreyfishing at gmail
Cleaned up code and removed unnecessary arguments.
70
    elif entry.kind == "symlink":
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
71
        item.type = tarfile.SYMTYPE
72
        item.size = 0
6619.3.14 by Jelmer Vernooij
Convert some octal numbers to new notations.
73
        item.mode = 0o755
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
74
        item.linkname = tree.get_symlink_target(tree_path)
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
75
        fileobj = None
76
    else:
5952.1.26 by Vincent Ladeuil
Fix the test failure, streams should be closed. In the right order.
77
        raise errors.BzrError("don't know how to export {%s} of kind %r"
6973.3.4 by Jelmer Vernooij
Don't assume entries returned by trees have a 'file_id' attribute.
78
                              % (file_id, entry.kind))
5952.1.4 by geoffreyfishing at gmail
Cleaned up export_tarball_item.
79
    return (item, fileobj)
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
80
5967.6.2 by Martin Pool
Delete fairly useless and repetitive per-format export single-call functions.
81
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
82
def tarball_generator(tree, root, subdir=None, force_mtime=None, format=''):
5967.6.3 by Martin Pool
Further shrink export code
83
    """Export tree contents to a tarball.
84
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
85
    :returns: A generator that will produce file content chunks.
5952.1.3 by geoffreyfishing at gmail
Updated code to requested format.
86
87
    :param tree: Tree to export
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
88
5952.1.3 by geoffreyfishing at gmail
Updated code to requested format.
89
    :param subdir: Sub directory to export
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
90
91
    :param force_mtime: Option mtime to force, instead of using tree
92
        timestamps.
5952.1.3 by geoffreyfishing at gmail
Updated code to requested format.
93
    """
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
94
    buf = BytesIO()
95
    with closing(tarfile.open(None, "w:%s" % format, buf)) as ball, tree.lock_read():
6331.2.1 by Jelmer Vernooij
Consistently pass tree path when exporting.
96
        for final_path, tree_path, entry in _export_iter_entries(tree, subdir):
5967.6.4 by Martin Pool
Close tarball from finally block (thanks jam)
97
            (item, fileobj) = prepare_tarball_item(
6331.2.1 by Jelmer Vernooij
Consistently pass tree path when exporting.
98
                tree, root, final_path, tree_path, entry, force_mtime)
5967.6.4 by Martin Pool
Close tarball from finally block (thanks jam)
99
            ball.addfile(item, fileobj)
6968.2.10 by Jelmer Vernooij
Review comments.
100
            # Yield the data that was written so far, rinse, repeat.
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
101
            yield buf.getvalue()
102
            buf.truncate(0)
103
            buf.seek(0)
104
    yield buf.getvalue()
105
106
107
def tgz_generator(tree, dest, root, subdir, force_mtime=None):
108
    """Export this tree to a new tar file.
109
110
    `dest` will be created holding the contents of this tree; if it
111
    already exists, it will be clobbered, like with "tar -c".
112
    """
113
    with tree.lock_read():
114
        import gzip
115
        if force_mtime is not None:
116
            root_mtime = force_mtime
117
        elif (getattr(tree, "repository", None) and
118
              getattr(tree, "get_revision_id", None)):
119
            # If this is a revision tree, use the revisions' timestamp
120
            rev = tree.repository.get_revision(tree.get_revision_id())
121
            root_mtime = rev.timestamp
6973.3.4 by Jelmer Vernooij
Don't assume entries returned by trees have a 'file_id' attribute.
122
        elif tree.is_versioned(u''):
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
123
            root_mtime = tree.get_file_mtime('')
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
124
        else:
125
            root_mtime = None
126
127
        is_stdout = False
128
        basename = None
129
        # gzip file is used with an explicit fileobj so that
130
        # the basename can be stored in the gzip file rather than
131
        # dest. (bug 102234)
132
        basename = os.path.basename(dest)
133
        buf = BytesIO()
134
        zipstream = gzip.GzipFile(basename, 'w', fileobj=buf,
135
                                  mtime=root_mtime)
7240.8.1 by Jelmer Vernooij
Use tree timestamp when exporting.
136
        for chunk in tarball_generator(tree, root, subdir, force_mtime):
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
137
            zipstream.write(chunk)
6968.2.10 by Jelmer Vernooij
Review comments.
138
            # Yield the data that was written so far, rinse, repeat.
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
139
            yield buf.getvalue()
140
            buf.truncate(0)
141
            buf.seek(0)
142
        # Closing zipstream may trigger writes to stream
143
        zipstream.close()
144
        yield buf.getvalue()
145
146
147
def tbz_generator(tree, dest, root, subdir, force_mtime=None):
148
    """Export this tree to a new tar file.
149
150
    `dest` will be created holding the contents of this tree; if it
151
    already exists, it will be clobbered, like with "tar -c".
152
    """
153
    return tarball_generator(
154
        tree, root, subdir, force_mtime, format='bz2')
155
156
157
def plain_tar_generator(tree, dest, root, subdir,
7143.15.2 by Jelmer Vernooij
Run autopep8.
158
                        force_mtime=None):
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
159
    """Export this tree to a new tar file.
160
161
    `dest` will be created holding the contents of this tree; if it
162
    already exists, it will be clobbered, like with "tar -c".
163
    """
164
    return tarball_generator(
165
        tree, root, subdir, force_mtime, format='')
166
167
168
def tar_xz_generator(tree, dest, root, subdir, force_mtime=None):
169
    return tar_lzma_generator(tree, dest, root, subdir, force_mtime, "xz")
170
171
172
def tar_lzma_generator(tree, dest, root, subdir, force_mtime=None,
173
                       compression_format="alone"):
5718.5.17 by Jelmer Vernooij
Support tar.lzma.
174
    """Export this tree to a new .tar.lzma file.
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
175
176
    `dest` will be created holding the contents of this tree; if it
177
    already exists, it will be clobbered, like with "tar -c".
178
    """
179
    try:
180
        import lzma
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
181
    except ImportError as e:
5718.5.10 by Jelmer Vernooij
Support creating .tar.xz files.
182
        raise errors.DependencyNotPresent('lzma', e)
183
7479.2.1 by Jelmer Vernooij
Drop python2 support.
184
    compressor = lzma.LZMACompressor(
185
        format={
186
            'xz': lzma.FORMAT_XZ,
187
            'raw': lzma.FORMAT_RAW,
188
            'alone': lzma.FORMAT_ALONE,
189
            }[compression_format])
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
190
191
    for chunk in tarball_generator(
192
            tree, root, subdir, force_mtime=force_mtime):
193
        yield compressor.compress(chunk)
194
195
    yield compressor.flush()