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