~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/export/tar_exporter.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Export a Tree to a non-versioned directory."""
 
17
"""Export a tree to a tarball."""
 
18
 
 
19
from __future__ import absolute_import
18
20
 
19
21
import os
20
22
import StringIO
26
28
    osutils,
27
29
    )
28
30
from bzrlib.export import _export_iter_entries
29
 
from bzrlib.filters import (
30
 
    ContentFilterContext,
31
 
    filtered_output_bytes,
32
 
    )
33
 
 
34
 
 
35
 
def prepare_tarball_item(tree, root, final_path, entry, filtered=False,
36
 
                         force_mtime=None):
 
31
 
 
32
 
 
33
def prepare_tarball_item(tree, root, final_path, tree_path, entry, force_mtime=None):
37
34
    """Prepare a tarball item for exporting
38
35
 
39
36
    :param tree: Tree to export
40
 
 
41
37
    :param final_path: Final path to place item
42
 
 
 
38
    :param tree_path: Path for the entry in the tree
43
39
    :param entry: Entry to export
44
 
 
45
 
    :param filtered: Whether to apply filters
46
 
 
47
40
    :param force_mtime: Option mtime to force, instead of using tree
48
41
        timestamps.
49
42
 
54
47
    if force_mtime is not None:
55
48
        item.mtime = force_mtime
56
49
    else:
57
 
        item.mtime = tree.get_file_mtime(entry.file_id, final_path)
 
50
        item.mtime = tree.get_file_mtime(entry.file_id, tree_path)
58
51
    if entry.kind == "file":
59
52
        item.type = tarfile.REGTYPE
60
 
        if tree.is_executable(entry.file_id):
 
53
        if tree.is_executable(entry.file_id, tree_path):
61
54
            item.mode = 0755
62
55
        else:
63
56
            item.mode = 0644
64
 
        if filtered:
65
 
            chunks = tree.get_file_lines(entry.file_id)
66
 
            filters = tree._content_filter_stack(final_path)
67
 
            context = ContentFilterContext(final_path, tree, entry)
68
 
            contents = filtered_output_bytes(chunks, filters, context)
69
 
            content = ''.join(contents)
70
 
            item.size = len(content)
71
 
            fileobj = StringIO.StringIO(content)
72
 
        else:
73
 
            item.size = tree.get_file_size(entry.file_id)
74
 
            fileobj = tree.get_file(entry.file_id)
 
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.
 
61
        content = tree.get_file_text(entry.file_id, tree_path)
 
62
        item.size = len(content)
 
63
        fileobj = StringIO.StringIO(content)
75
64
    elif entry.kind == "directory":
76
65
        item.type = tarfile.DIRTYPE
77
66
        item.name += '/'
82
71
        item.type = tarfile.SYMTYPE
83
72
        item.size = 0
84
73
        item.mode = 0755
85
 
        item.linkname = tree.get_symlink_target(entry.file_id)
 
74
        item.linkname = tree.get_symlink_target(entry.file_id, tree_path)
86
75
        fileobj = None
87
76
    else:
88
77
        raise errors.BzrError("don't know how to export {%s} of kind %r"
90
79
    return (item, fileobj)
91
80
 
92
81
 
93
 
def export_tarball_generator(tree, ball, root, subdir=None, filtered=False,
94
 
                   force_mtime=None):
 
82
def export_tarball_generator(tree, ball, root, subdir=None, force_mtime=None):
95
83
    """Export tree contents to a tarball.
96
84
 
97
85
    :returns: A generator that will repeatedly produce None as each file is
103
91
    :param ball: Tarball to export to; it will be closed when writing is
104
92
        complete.
105
93
 
106
 
    :param filtered: Whether to apply filters
107
 
 
108
94
    :param subdir: Sub directory to export
109
95
 
110
96
    :param force_mtime: Option mtime to force, instead of using tree
111
97
        timestamps.
112
98
    """
113
99
    try:
114
 
        for final_path, entry in _export_iter_entries(tree, subdir):
 
100
        for final_path, tree_path, entry in _export_iter_entries(tree, subdir):
115
101
            (item, fileobj) = prepare_tarball_item(
116
 
                tree, root, final_path, entry, filtered, force_mtime)
 
102
                tree, root, final_path, tree_path, entry, force_mtime)
117
103
            ball.addfile(item, fileobj)
118
104
            yield
119
105
    finally:
120
106
        ball.close()
121
107
 
122
108
 
123
 
def tgz_exporter_generator(tree, dest, root, subdir, filtered=False,
124
 
                           force_mtime=None, fileobj=None):
 
109
def tgz_exporter_generator(tree, dest, root, subdir, force_mtime=None,
 
110
    fileobj=None):
125
111
    """Export this tree to a new tar file.
126
112
 
127
113
    `dest` will be created holding the contents of this tree; if it
161
147
        zipstream = gzip.GzipFile(basename, 'w', fileobj=stream)
162
148
    ball = tarfile.open(None, 'w|', fileobj=zipstream)
163
149
    for _ in export_tarball_generator(
164
 
        tree, ball, root, subdir, filtered, force_mtime):
 
150
        tree, ball, root, subdir, force_mtime):
165
151
        yield
166
152
    # Closing zipstream may trigger writes to stream
167
153
    zipstream.close()
170
156
        stream.close()
171
157
 
172
158
 
173
 
def tbz_exporter_generator(tree, dest, root, subdir, filtered=False,
 
159
def tbz_exporter_generator(tree, dest, root, subdir,
174
160
                           force_mtime=None, fileobj=None):
175
161
    """Export this tree to a new tar file.
176
162
 
189
175
        # Python 2.6.5 and 2.7b1)
190
176
        ball = tarfile.open(dest.encode(osutils._fs_enc), 'w:bz2')
191
177
    return export_tarball_generator(
192
 
        tree, ball, root, subdir, filtered, force_mtime)
 
178
        tree, ball, root, subdir, force_mtime)
193
179
 
194
180
 
195
181
def plain_tar_exporter_generator(tree, dest, root, subdir, compression=None,
196
 
                                 filtered=False, force_mtime=None,
197
 
                                 fileobj=None):
 
182
    force_mtime=None, fileobj=None):
198
183
    """Export this tree to a new tar file.
199
184
 
200
185
    `dest` will be created holding the contents of this tree; if it
208
193
        stream = open(dest, 'wb')
209
194
    ball = tarfile.open(None, 'w|', stream)
210
195
    return export_tarball_generator(
211
 
        tree, ball, root, subdir, filtered, force_mtime)
212
 
 
213
 
 
214
 
def tar_xz_exporter_generator(tree, dest, root, subdir, filtered=False,
 
196
        tree, ball, root, subdir, force_mtime)
 
197
 
 
198
 
 
199
def tar_xz_exporter_generator(tree, dest, root, subdir,
215
200
                              force_mtime=None, fileobj=None):
216
 
    return tar_lzma_exporter_generator(tree, dest, root, subdir, filtered,
 
201
    return tar_lzma_exporter_generator(tree, dest, root, subdir,
217
202
                                       force_mtime, fileobj, "xz")
218
203
 
219
204
 
220
 
def tar_lzma_exporter_generator(tree, dest, root, subdir, filtered=False,
 
205
def tar_lzma_exporter_generator(tree, dest, root, subdir,
221
206
                      force_mtime=None, fileobj=None,
222
207
                                compression_format="alone"):
223
208
    """Export this tree to a new .tar.lzma file.
240
225
        options={"format": compression_format})
241
226
    ball = tarfile.open(None, 'w:', fileobj=stream)
242
227
    return export_tarball_generator(
243
 
        tree, ball, root, subdir, filtered=filtered, force_mtime=force_mtime)
 
228
        tree, ball, root, subdir, force_mtime=force_mtime)