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