81
82
return (item, fileobj)
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.
87
:returns: A generator that will repeatedly produce None as each file is
88
emitted. The entire generator must be consumed to complete writing
88
:returns: A generator that will produce file content chunks.
91
90
:param tree: Tree to export
93
:param ball: Tarball to export to; it will be closed when writing is
96
92
:param subdir: Sub directory to export
98
94
:param force_mtime: Option mtime to force, instead of using tree
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)
111
def tgz_exporter_generator(tree, dest, root, subdir, force_mtime=None,
113
"""Export this tree to a new tar file.
115
`dest` will be created holding the contents of this tree; if it
116
already exists, it will be clobbered, like with "tar -c".
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())
133
if fileobj is not None:
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
143
basename = os.path.basename(dest)
144
zipstream = gzip.GzipFile(basename, 'w', fileobj=stream,
146
ball = tarfile.open(None, 'w|', fileobj=zipstream)
147
for _ in export_tarball_generator(
148
tree, ball, root, subdir, force_mtime):
150
# Closing zipstream may trigger writes to stream
153
# Now we can safely close the stream
157
def tbz_exporter_generator(tree, dest, root, subdir,
158
force_mtime=None, fileobj=None):
159
"""Export this tree to a new tar file.
161
`dest` will be created holding the contents of this tree; if it
162
already exists, it will be clobbered, like with "tar -c".
164
if fileobj is not None:
165
ball = tarfile.open(None, 'w|bz2', fileobj)
167
ball = tarfile.open(None, 'w|bz2', sys.stdout)
169
ball = tarfile.open(dest, 'w:bz2')
170
return export_tarball_generator(
171
tree, ball, root, subdir, force_mtime)
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.
178
`dest` will be created holding the contents of this tree; if it
179
already exists, it will be clobbered, like with "tar -c".
181
if fileobj is not None:
186
stream = open(dest, 'wb')
187
ball = tarfile.open(None, 'w|', stream)
188
return export_tarball_generator(
189
tree, ball, root, subdir, force_mtime)
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")
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.
110
def tgz_generator(tree, dest, root, subdir, force_mtime=None):
111
"""Export this tree to a new tar file.
113
`dest` will be created holding the contents of this tree; if it
114
already exists, it will be clobbered, like with "tar -c".
116
with tree.lock_read():
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())
132
# gzip file is used with an explicit fileobj so that
133
# the basename can be stored in the gzip file rather than
135
basename = os.path.basename(dest)
137
zipstream = gzip.GzipFile(basename, 'w', fileobj=buf,
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.
146
# Closing zipstream may trigger writes to stream
151
def tbz_generator(tree, dest, root, subdir, force_mtime=None):
152
"""Export this tree to a new tar file.
154
`dest` will be created holding the contents of this tree; if it
155
already exists, it will be clobbered, like with "tar -c".
157
return tarball_generator(
158
tree, root, subdir, force_mtime, format='bz2')
161
def plain_tar_generator(tree, dest, root, subdir,
163
"""Export this tree to a new tar file.
165
`dest` will be created holding the contents of this tree; if it
166
already exists, it will be clobbered, like with "tar -c".
168
return tarball_generator(
169
tree, root, subdir, force_mtime, format='')
172
def tar_xz_generator(tree, dest, root, subdir, force_mtime=None):
173
return tar_lzma_generator(tree, dest, root, subdir, force_mtime, "xz")
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.
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".
207
raise errors.BzrError("Writing to stdout not supported for .tar.lzma")
209
if fileobj is not None:
210
raise errors.BzrError(
211
"Writing to fileobject not supported for .tar.lzma")
214
185
except ImportError as e:
215
186
raise errors.DependencyNotPresent('lzma', e)
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})
191
for chunk in tarball_generator(
192
tree, root, subdir, force_mtime=force_mtime):
193
yield compressor.compress(chunk)
195
yield compressor.flush()