/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/tar.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-20 15:54:59 UTC
  • mfrom: (6968.2.10 archive)
  • mto: This revision was merged to the branch mainline in revision 6973.
  • Revision ID: jelmer@jelmer.uk-20180520155459-4u1tpealx8jj3sy3
Merge archive branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from __future__ import absolute_import
20
20
 
 
21
from contextlib import closing
21
22
import os
22
23
import sys
23
24
import tarfile
81
82
    return (item, fileobj)
82
83
 
83
84
 
84
 
def export_tarball_generator(tree, ball, root, subdir=None, force_mtime=None):
 
85
def tarball_generator(tree, root, subdir=None, force_mtime=None, format=''):
85
86
    """Export tree contents to a tarball.
86
87
 
87
 
    :returns: A generator that will repeatedly produce None as each file is
88
 
        emitted.  The entire generator must be consumed to complete writing
89
 
        the file.
 
88
    :returns: A generator that will produce file content chunks.
90
89
 
91
90
    :param tree: Tree to export
92
91
 
93
 
    :param ball: Tarball to export to; it will be closed when writing is
94
 
        complete.
95
 
 
96
92
    :param subdir: Sub directory to export
97
93
 
98
94
    :param force_mtime: Option mtime to force, instead of using tree
99
95
        timestamps.
100
96
    """
101
 
    try:
 
97
    buf = BytesIO()
 
98
    with closing(tarfile.open(None, "w:%s" % format, buf)) as ball, tree.lock_read():
102
99
        for final_path, tree_path, entry in _export_iter_entries(tree, subdir):
103
100
            (item, fileobj) = prepare_tarball_item(
104
101
                tree, root, final_path, tree_path, entry, force_mtime)
105
102
            ball.addfile(item, fileobj)
106
 
            yield
107
 
    finally:
108
 
        ball.close()
109
 
 
110
 
 
111
 
def tgz_exporter_generator(tree, dest, root, subdir, force_mtime=None,
112
 
    fileobj=None):
113
 
    """Export this tree to a new tar file.
114
 
 
115
 
    `dest` will be created holding the contents of this tree; if it
116
 
    already exists, it will be clobbered, like with "tar -c".
117
 
    """
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
126
 
    elif tree.get_root_id() is not None:
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
 
    if fileobj is not None:
134
 
        stream = fileobj
135
 
    elif dest == '-':
136
 
        stream = sys.stdout
137
 
        is_stdout = True
138
 
    else:
139
 
        stream = open(dest, 'wb')
140
 
    # gzip file is used with an explicit fileobj so that
141
 
    # the basename can be stored in the gzip file rather than
142
 
    # dest. (bug 102234)
143
 
    basename = os.path.basename(dest)
144
 
    zipstream = gzip.GzipFile(basename, 'w', fileobj=stream,
145
 
                              mtime=root_mtime)
146
 
    ball = tarfile.open(None, 'w|', fileobj=zipstream)
147
 
    for _ in export_tarball_generator(
148
 
        tree, ball, root, subdir, force_mtime):
149
 
        yield
150
 
    # Closing zipstream may trigger writes to stream
151
 
    zipstream.close()
152
 
    if not is_stdout:
153
 
        # Now we can safely close the stream
154
 
        stream.close()
155
 
 
156
 
 
157
 
def tbz_exporter_generator(tree, dest, root, subdir,
158
 
                           force_mtime=None, fileobj=None):
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
 
    if fileobj is not None:
165
 
        ball = tarfile.open(None, 'w|bz2', fileobj)
166
 
    elif dest == '-':
167
 
        ball = tarfile.open(None, 'w|bz2', sys.stdout)
168
 
    else:
169
 
        ball = tarfile.open(dest, 'w:bz2')
170
 
    return export_tarball_generator(
171
 
        tree, ball, root, subdir, force_mtime)
172
 
 
173
 
 
174
 
def plain_tar_exporter_generator(tree, dest, root, subdir, compression=None,
175
 
    force_mtime=None, fileobj=None):
176
 
    """Export this tree to a new tar file.
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
 
    if fileobj is not None:
182
 
        stream = fileobj
183
 
    elif dest == '-':
184
 
        stream = sys.stdout
185
 
    else:
186
 
        stream = open(dest, 'wb')
187
 
    ball = tarfile.open(None, 'w|', stream)
188
 
    return export_tarball_generator(
189
 
        tree, ball, root, subdir, force_mtime)
190
 
 
191
 
 
192
 
def tar_xz_exporter_generator(tree, dest, root, subdir,
193
 
                              force_mtime=None, fileobj=None):
194
 
    return tar_lzma_exporter_generator(tree, dest, root, subdir,
195
 
                                       force_mtime, fileobj, "xz")
196
 
 
197
 
 
198
 
def tar_lzma_exporter_generator(tree, dest, root, subdir,
199
 
                      force_mtime=None, fileobj=None,
200
 
                                compression_format="alone"):
 
103
            # Yield the data that was written so far, rinse, repeat.
 
104
            yield buf.getvalue()
 
105
            buf.truncate(0)
 
106
            buf.seek(0)
 
107
    yield buf.getvalue()
 
108
 
 
109
 
 
110
def tgz_generator(tree, dest, root, subdir, force_mtime=None):
 
111
    """Export this tree to a new tar file.
 
112
 
 
113
    `dest` will be created holding the contents of this tree; if it
 
114
    already exists, it will be clobbered, like with "tar -c".
 
115
    """
 
116
    with tree.lock_read():
 
117
        import gzip
 
118
        if force_mtime is not None:
 
119
            root_mtime = force_mtime
 
120
        elif (getattr(tree, "repository", None) and
 
121
              getattr(tree, "get_revision_id", None)):
 
122
            # If this is a revision tree, use the revisions' timestamp
 
123
            rev = tree.repository.get_revision(tree.get_revision_id())
 
124
            root_mtime = rev.timestamp
 
125
        elif tree.get_root_id() is not None:
 
126
            root_mtime = tree.get_file_mtime('', tree.get_root_id())
 
127
        else:
 
128
            root_mtime = None
 
129
 
 
130
        is_stdout = False
 
131
        basename = None
 
132
        # gzip file is used with an explicit fileobj so that
 
133
        # the basename can be stored in the gzip file rather than
 
134
        # dest. (bug 102234)
 
135
        basename = os.path.basename(dest)
 
136
        buf = BytesIO()
 
137
        zipstream = gzip.GzipFile(basename, 'w', fileobj=buf,
 
138
                                  mtime=root_mtime)
 
139
        for chunk in tarball_generator(
 
140
            tree, root, subdir, force_mtime):
 
141
            zipstream.write(chunk)
 
142
            # Yield the data that was written so far, rinse, repeat.
 
143
            yield buf.getvalue()
 
144
            buf.truncate(0)
 
145
            buf.seek(0)
 
146
        # Closing zipstream may trigger writes to stream
 
147
        zipstream.close()
 
148
        yield buf.getvalue()
 
149
 
 
150
 
 
151
def tbz_generator(tree, dest, root, subdir, force_mtime=None):
 
152
    """Export this tree to a new tar file.
 
153
 
 
154
    `dest` will be created holding the contents of this tree; if it
 
155
    already exists, it will be clobbered, like with "tar -c".
 
156
    """
 
157
    return tarball_generator(
 
158
        tree, root, subdir, force_mtime, format='bz2')
 
159
 
 
160
 
 
161
def plain_tar_generator(tree, dest, root, subdir,
 
162
    force_mtime=None):
 
163
    """Export this tree to a new tar file.
 
164
 
 
165
    `dest` will be created holding the contents of this tree; if it
 
166
    already exists, it will be clobbered, like with "tar -c".
 
167
    """
 
168
    return tarball_generator(
 
169
        tree, root, subdir, force_mtime, format='')
 
170
 
 
171
 
 
172
def tar_xz_generator(tree, dest, root, subdir, force_mtime=None):
 
173
    return tar_lzma_generator(tree, dest, root, subdir, force_mtime, "xz")
 
174
 
 
175
 
 
176
def tar_lzma_generator(tree, dest, root, subdir, force_mtime=None,
 
177
                       compression_format="alone"):
201
178
    """Export this tree to a new .tar.lzma file.
202
179
 
203
180
    `dest` will be created holding the contents of this tree; if it
204
181
    already exists, it will be clobbered, like with "tar -c".
205
182
    """
206
 
    if dest == '-':
207
 
        raise errors.BzrError("Writing to stdout not supported for .tar.lzma")
208
 
 
209
 
    if fileobj is not None:
210
 
        raise errors.BzrError(
211
 
            "Writing to fileobject not supported for .tar.lzma")
212
183
    try:
213
184
        import lzma
214
185
    except ImportError as e:
215
186
        raise errors.DependencyNotPresent('lzma', e)
216
187
 
217
 
    stream = lzma.LZMAFile(dest.encode(osutils._fs_enc), 'w',
218
 
        options={"format": compression_format})
219
 
    ball = tarfile.open(None, 'w:', fileobj=stream)
220
 
    return export_tarball_generator(
221
 
        tree, ball, root, subdir, force_mtime=force_mtime)
 
188
    compressor = lzma.LZMACompressor(
 
189
            options={"format": compression_format})
 
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()