Rev 5961: (vila) Exporting may now be done with a generator (Geoff) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Jun 7 17:21:53 UTC 2011
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 5961 [merge]
revision-id: pqm at pqm.ubuntu.com-20110607172150-b8tdisesgnjxk7ku
parent: pqm at pqm.ubuntu.com-20110607134912-0icu0bcbn5ss4mod
parent: v.ladeuil+lp at free.fr-20110607151855-iy796hvhizjme4rq
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2011-06-07 17:21:50 +0000
message:
(vila) Exporting may now be done with a generator (Geoff)
modified:
bzrlib/export/__init__.py __init__.py-20051114235828-1ba62cb4062304e6
bzrlib/export/dir_exporter.py dir_exporter.py-20051114235828-b51397f56bc7b117
bzrlib/export/tar_exporter.py tar_exporter.py-20051114235828-1f6349a2f090a5d0
bzrlib/export/zip_exporter.py zip_exporter.py-20051114235828-8f57f954fba6497e
bzrlib/tests/blackbox/test_export.py test_export.py-20051229024010-e6c26658e460fb1c
doc/en/release-notes/bzr-2.4.txt bzr2.4.txt-20110114053217-k7ym9jfz243fddjm-1
doc/en/whats-new/whats-new-in-2.4.txt whatsnewin2.4.txt-20110114044330-nipk1og7j729fy89-1
=== modified file 'bzrlib/export/__init__.py'
--- a/bzrlib/export/__init__.py 2011-04-28 06:45:01 +0000
+++ b/bzrlib/export/__init__.py 2011-06-07 15:18:55 +0000
@@ -59,40 +59,48 @@
When requesting a specific type of export, load the respective path.
"""
- def _loader(tree, dest, root, subdir, filtered, force_mtime):
+ def _loader(tree, dest, root, subdir, filtered, force_mtime, fileobj):
func = pyutils.get_named_object(module, funcname)
- return func(tree, dest, root, subdir, filtered=filtered,
- force_mtime=force_mtime)
+ return func(tree, dest, root, subdir, filtered=filtered,
+ force_mtime=force_mtime, fileobj=fileobj)
register_exporter(scheme, extensions, _loader)
-
-
-def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
- per_file_timestamps=False):
- """Export the given Tree to the specific destination.
+
+def get_export_generator(tree, dest=None, format=None, root=None, subdir=None,
+ filtered=False, per_file_timestamps=False,
+ fileobj=None):
+ """Returns a generator that exports the given tree.
+
+ The generator is expected to yield None while exporting the tree while the
+ actual export is written to ``fileobj``.
:param tree: A Tree (such as RevisionTree) to export
- :param dest: The destination where the files,etc should be put
+
+ :param dest: The destination where the files, etc should be put
+
:param format: The format (dir, zip, etc), if None, it will check the
- extension on dest, looking for a match
- :param root: The root location inside the format.
- It is common practise to have zipfiles and tarballs
- extract into a subdirectory, rather than into the
- current working directory.
- If root is None, the default root will be
- selected as the destination without its
- extension.
+ extension on dest, looking for a match
+
+ :param root: The root location inside the format. It is common practise to
+ have zipfiles and tarballs extract into a subdirectory, rather than
+ into the current working directory. If root is None, the default root
+ will be selected as the destination without its extension.
+
:param subdir: A starting directory within the tree. None means to export
the entire tree, and anything else should specify the relative path to
a directory to start exporting from.
- :param filtered: If True, content filtering is applied to the
- files exported.
- :param per_file_timestamps: Whether to use the timestamp stored in the
- tree rather than now(). This will do a revision lookup
- for every file so will be significantly slower.
+
+ :param filtered: If True, content filtering is applied to the exported
+ files.
+
+ :param per_file_timestamps: Whether to use the timestamp stored in the tree
+ rather than now(). This will do a revision lookup for every file so
+ will be significantly slower.
+
+ :param fileobj: Optional file object to use
"""
global _exporters, _exporter_extensions
- if format is None:
+ if format is None and dest is not None:
for ext in _exporter_extensions:
if dest.endswith(ext):
format = _exporter_extensions[ext]
@@ -113,14 +121,48 @@
trace.mutter('export version %r', tree)
- tree.lock_read()
try:
- return _exporters[format](tree, dest, root, subdir, filtered=filtered,
- force_mtime=force_mtime)
- finally:
+ tree.lock_read()
+
+ for _ in _exporters[format](tree, dest, root, subdir,
+ filtered=filtered,
+ force_mtime=force_mtime, fileobj=fileobj):
+
+ yield
+ finally:
tree.unlock()
+def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
+ per_file_timestamps=False, fileobj=None):
+ """Export the given Tree to the specific destination.
+
+ :param tree: A Tree (such as RevisionTree) to export
+ :param dest: The destination where the files,etc should be put
+ :param format: The format (dir, zip, etc), if None, it will check the
+ extension on dest, looking for a match
+ :param root: The root location inside the format.
+ It is common practise to have zipfiles and tarballs
+ extract into a subdirectory, rather than into the
+ current working directory.
+ If root is None, the default root will be
+ selected as the destination without its
+ extension.
+ :param subdir: A starting directory within the tree. None means to export
+ the entire tree, and anything else should specify the relative path to
+ a directory to start exporting from.
+ :param filtered: If True, content filtering is applied to the
+ files exported.
+ :param per_file_timestamps: Whether to use the timestamp stored in the
+ tree rather than now(). This will do a revision lookup
+ for every file so will be significantly slower.
+ :param fileobj: Optional file object to use
+ """
+ for _ in get_export_generator(tree, dest, format, root, subdir, filtered,
+ per_file_timestamps, fileobj):
+
+ pass
+
def get_root_name(dest):
"""Get just the root name for an export.
@@ -167,15 +209,24 @@
final_path = path
if not tree.has_filename(path):
continue
+
yield final_path, entry
-register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter', 'dir_exporter')
-register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter', 'dir_exporter')
-register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter', 'plain_tar_exporter')
-register_lazy_exporter('tgz', ['.tar.gz', '.tgz'], 'bzrlib.export.tar_exporter', 'tgz_exporter')
-register_lazy_exporter('tbz2', ['.tar.bz2', '.tbz2'], 'bzrlib.export.tar_exporter', 'tbz_exporter')
-register_lazy_exporter('tlzma', ['.tar.lzma'], 'bzrlib.export.tar_exporter', 'tar_lzma_exporter')
-register_lazy_exporter('txz', ['.tar.xz'], 'bzrlib.export.tar_exporter', 'tar_xz_exporter')
-register_lazy_exporter('zip', ['.zip'], 'bzrlib.export.zip_exporter', 'zip_exporter')
+register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter',
+ 'dir_exporter_generator')
+register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter',
+ 'dir_exporter_generator')
+register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter',
+ 'plain_tar_exporter_generator')
+register_lazy_exporter('tgz', ['.tar.gz', '.tgz'], 'bzrlib.export.tar_exporter',
+ 'tgz_exporter_generator')
+register_lazy_exporter('tbz2', ['.tar.bz2', '.tbz2'],
+ 'bzrlib.export.tar_exporter', 'tbz_exporter_generator')
+register_lazy_exporter('tlzma', ['.tar.lzma'], 'bzrlib.export.tar_exporter',
+ 'tar_lzma_exporter_generator')
+register_lazy_exporter('txz', ['.tar.xz'], 'bzrlib.export.tar_exporter',
+ 'tar_xz_exporter_generator')
+register_lazy_exporter('zip', ['.zip'], 'bzrlib.export.zip_exporter',
+ 'zip_exporter_generator')
=== modified file 'bzrlib/export/dir_exporter.py'
--- a/bzrlib/export/dir_exporter.py 2011-03-13 21:30:33 +0000
+++ b/bzrlib/export/dir_exporter.py 2011-06-06 09:31:59 +0000
@@ -27,11 +27,14 @@
)
-def dir_exporter(tree, dest, root, subdir=None, filtered=False, force_mtime=None):
- """Export this tree to a new directory.
+def dir_exporter_generator(tree, dest, root, subdir=None, filtered=False,
+ force_mtime=None, fileobj=None):
+ """Return a generator that exports this tree to a new directory.
`dest` should either not exist or should be empty. If it does not exist it
will be created holding the contents of this tree.
+
+ :param fileobj: Is not used in this exporter
:note: If the export fails, the destination directory will be
left in an incompletely exported state: export is not transactional.
@@ -42,7 +45,8 @@
if e.errno == errno.EEXIST:
# check if directory empty
if os.listdir(dest) != []:
- raise errors.BzrError("Can't export tree to non-empty directory.")
+ raise errors.BzrError(
+ "Can't export tree to non-empty directory.")
else:
raise
# Iterate everything, building up the files we will want to export, and
@@ -69,6 +73,8 @@
else:
raise errors.BzrError("don't know how to export {%s} of kind %r" %
(ie.file_id, ie.kind))
+
+ yield
# The data returned here can be in any order, but we've already created all
# the directories
flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | getattr(os, 'O_BINARY', 0)
@@ -92,3 +98,12 @@
else:
mtime = tree.get_file_mtime(tree.path2id(relpath), relpath)
os.utime(fullpath, (mtime, mtime))
+
+ yield
+
+def dir_exporter(tree, dest, root, subdir=None, filtered=False,
+ force_mtime=None, fileobj=None):
+
+ for _ in dir_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj):
+ pass
=== modified file 'bzrlib/export/tar_exporter.py'
--- a/bzrlib/export/tar_exporter.py 2011-05-13 21:05:38 +0000
+++ b/bzrlib/export/tar_exporter.py 2011-06-07 13:33:41 +0000
@@ -14,8 +14,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-"""Export a Tree to a non-versioned directory.
-"""
+"""Export a Tree to a non-versioned directory."""
import os
import StringIO
@@ -32,61 +31,95 @@
filtered_output_bytes,
)
-
-def export_tarball(tree, ball, root, subdir=None, filtered=False,
+def prepare_tarball_item(tree, root, final_path, entry, filtered=False,
+ force_mtime=None):
+ """Prepare a tarball item for exporting
+
+ :param tree: Tree to export
+
+ :param final_path: Final path to place item
+
+ :param entry: Entry to export
+
+ :param filtered: Whether to apply filters
+
+ :param force_mtime: Option mtime to force, instead of using tree timestamps.
+
+ Returns a (tarinfo, fileobj) tuple
+ """
+ filename = osutils.pathjoin(root, final_path).encode('utf8')
+ item = tarfile.TarInfo(filename)
+ if force_mtime is not None:
+ item.mtime = force_mtime
+ else:
+ item.mtime = tree.get_file_mtime(entry.file_id, final_path)
+ if entry.kind == "file":
+ item.type = tarfile.REGTYPE
+ if tree.is_executable(entry.file_id):
+ item.mode = 0755
+ else:
+ item.mode = 0644
+ if filtered:
+ chunks = tree.get_file_lines(entry.file_id)
+ filters = tree._content_filter_stack(final_path)
+ context = ContentFilterContext(final_path, tree, entry)
+ contents = filtered_output_bytes(chunks, filters, context)
+ content = ''.join(contents)
+ item.size = len(content)
+ fileobj = StringIO.StringIO(content)
+ else:
+ item.size = tree.get_file_size(entry.file_id)
+ fileobj = tree.get_file(entry.file_id)
+ elif entry.kind == "directory":
+ item.type = tarfile.DIRTYPE
+ item.name += '/'
+ item.size = 0
+ item.mode = 0755
+ fileobj = None
+ elif entry.kind == "symlink":
+ item.type = tarfile.SYMTYPE
+ item.size = 0
+ item.mode = 0755
+ item.linkname = tree.get_symlink_target(entry.file_id)
+ fileobj = None
+ else:
+ raise errors.BzrError("don't know how to export {%s} of kind %r"
+ % (entry.file_id, entry.kind))
+ return (item, fileobj)
+
+def export_tarball_generator(tree, ball, root, subdir=None, filtered=False,
force_mtime=None):
- """Export tree contents to a tarball.
+ """Export tree contents to a tarball. This is a generator.
:param tree: Tree to export
+
:param ball: Tarball to export to
+
:param filtered: Whether to apply filters
+
:param subdir: Sub directory to export
- :param force_mtime: Option mtime to force, instead of using
- tree timestamps.
+
+ :param force_mtime: Option mtime to force, instead of using tree
+ timestamps.
"""
- for dp, ie in _export_iter_entries(tree, subdir):
- filename = osutils.pathjoin(root, dp).encode('utf8')
- item = tarfile.TarInfo(filename)
- if force_mtime is not None:
- item.mtime = force_mtime
- else:
- item.mtime = tree.get_file_mtime(ie.file_id, dp)
- if ie.kind == "file":
- item.type = tarfile.REGTYPE
- if tree.is_executable(ie.file_id):
- item.mode = 0755
- else:
- item.mode = 0644
- if filtered:
- chunks = tree.get_file_lines(ie.file_id)
- filters = tree._content_filter_stack(dp)
- context = ContentFilterContext(dp, tree, ie)
- contents = filtered_output_bytes(chunks, filters, context)
- content = ''.join(contents)
- item.size = len(content)
- fileobj = StringIO.StringIO(content)
- else:
- item.size = tree.get_file_size(ie.file_id)
- fileobj = tree.get_file(ie.file_id)
- elif ie.kind == "directory":
- item.type = tarfile.DIRTYPE
- item.name += '/'
- item.size = 0
- item.mode = 0755
- fileobj = None
- elif ie.kind == "symlink":
- item.type = tarfile.SYMTYPE
- item.size = 0
- item.mode = 0755
- item.linkname = tree.get_symlink_target(ie.file_id)
- fileobj = None
- else:
- raise errors.BzrError("don't know how to export {%s} of kind %r" %
- (ie.file_id, ie.kind))
+ for final_path, entry in _export_iter_entries(tree, subdir):
+
+ (item, fileobj) = prepare_tarball_item(tree, root, final_path,
+ entry, filtered, force_mtime)
ball.addfile(item, fileobj)
-
-def tgz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None):
+ yield
+
+
+def export_tarball(tree, ball, root, subdir=None, filtered=False,
+ force_mtime=None):
+
+ for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
+ force_mtime):
+ pass
+
+def tgz_exporter_generator(tree, dest, root, subdir, filtered=False,
+ force_mtime=None, fileobj=None):
"""Export this tree to a new tar file.
`dest` will be created holding the contents of this tree; if it
@@ -106,7 +139,9 @@
root_mtime = None
is_stdout = False
- if dest == '-':
+ if fileobj is not None:
+ stream = fileobj
+ elif dest == '-':
basename = None
stream = sys.stdout
is_stdout = True
@@ -117,26 +152,44 @@
# dest. (bug 102234)
basename = os.path.basename(dest)
try:
- zipstream = gzip.GzipFile(basename, 'w', fileobj=stream, mtime=root_mtime)
+ zipstream = gzip.GzipFile(basename, 'w', fileobj=stream,
+ mtime=root_mtime)
except TypeError:
# Python < 2.7 doesn't support the mtime argument
zipstream = gzip.GzipFile(basename, 'w', fileobj=stream)
ball = tarfile.open(None, 'w|', fileobj=zipstream)
- export_tarball(tree, ball, root, subdir, filtered=filtered,
- force_mtime=force_mtime)
+
+ for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
+ force_mtime):
+
+ yield
+ # Closing ball may trigger writes to zipstream
ball.close()
+ # Closing zipstream may trigger writes to stream
zipstream.close()
if not is_stdout:
+ # Now we can safely close the stream
stream.close()
-def tbz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None):
+def tgz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None,
+ fileobj=None):
+
+ for _ in tgz_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj):
+ pass
+
+
+def tbz_exporter_generator(tree, dest, root, subdir, filtered=False,
+ force_mtime=None, fileobj=None):
"""Export this tree to a new tar file.
`dest` will be created holding the contents of this tree; if it
already exists, it will be clobbered, like with "tar -c".
"""
- if dest == '-':
+ if fileobj is not None:
+ ball = tarfile.open(None, 'w|bz2', fileobj)
+ elif dest == '-':
ball = tarfile.open(None, 'w|bz2', sys.stdout)
else:
# tarfile.open goes on to do 'os.getcwd() + dest' for opening
@@ -145,35 +198,70 @@
# upstream python bug http://bugs.python.org/issue8396
# (fixed in Python 2.6.5 and 2.7b1)
ball = tarfile.open(dest.encode(osutils._fs_enc), 'w:bz2')
- export_tarball(tree, ball, root, subdir, filtered=filtered,
- force_mtime=force_mtime)
- ball.close()
-
+
+ for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
+ force_mtime):
+ yield
+
+ ball.close()
+
+
+def tbz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None,
+ fileobj=None):
+
+ for _ in tbz_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj):
+ pass
+
+
+def plain_tar_exporter_generator(tree, dest, root, subdir, compression=None,
+ filtered=False, force_mtime=None,
+ fileobj=None):
+ """Export this tree to a new tar file.
+
+ `dest` will be created holding the contents of this tree; if it
+ already exists, it will be clobbered, like with "tar -c".
+ """
+ if fileobj is not None:
+ stream = fileobj
+ elif dest == '-':
+ stream = sys.stdout
+ else:
+ stream = open(dest, 'wb')
+ ball = tarfile.open(None, 'w|', stream)
+
+ for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
+ force_mtime):
+
+ yield
+
+ ball.close()
def plain_tar_exporter(tree, dest, root, subdir, compression=None,
- filtered=False, force_mtime=None):
- """Export this tree to a new tar file.
-
- `dest` will be created holding the contents of this tree; if it
- already exists, it will be clobbered, like with "tar -c".
- """
- if dest == '-':
- stream = sys.stdout
- else:
- stream = open(dest, 'wb')
- ball = tarfile.open(None, 'w|', stream)
- export_tarball(tree, ball, root, subdir, filtered=filtered,
- force_mtime=force_mtime)
- ball.close()
-
-
-def tar_xz_exporter(tree, dest, root, subdir, filtered=False,
- force_mtime=None):
- return tar_lzma_exporter(tree, dest, root, subdir, filtered=filtered,
- force_mtime=force_mtime, compression_format="xz")
-
-
-def tar_lzma_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None, compression_format="alone"):
+ filtered=False, force_mtime=None, fileobj=None):
+
+ for _ in plain_tar_exporter_generator(
+ tree, dest, root, subdir, compression, filtered, force_mtime, fileobj):
+ pass
+
+
+def tar_xz_exporter_generator(tree, dest, root, subdir, filtered=False,
+ force_mtime=None, fileobj=None):
+
+ return tar_lzma_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj, "xz")
+
+
+def tar_xz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None,
+ fileobj=None):
+ for _ in tar_xz_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj):
+ pass
+
+
+def tar_lzma_exporter_generator(tree, dest, root, subdir, filtered=False,
+ force_mtime=None, fileobj=None,
+ compression_format="alone"):
"""Export this tree to a new .tar.lzma file.
`dest` will be created holding the contents of this tree; if it
@@ -182,6 +270,9 @@
if dest == '-':
raise errors.BzrError("Writing to stdout not supported for .tar.lzma")
+ if fileobj is not None:
+ raise errors.BzrError(
+ "Writing to fileobject not supported for .tar.lzma")
try:
import lzma
except ImportError, e:
@@ -190,7 +281,18 @@
stream = lzma.LZMAFile(dest.encode(osutils._fs_enc), 'w',
options={"format": compression_format})
ball = tarfile.open(None, 'w:', fileobj=stream)
- export_tarball(tree, ball, root, subdir, filtered=filtered,
- force_mtime=force_mtime)
+
+ for _ in export_tarball_generator(
+ tree, ball, root, subdir, filtered=filtered, force_mtime=force_mtime):
+ yield
+
ball.close()
+
+def tar_lzma_exporter(tree, dest, root, subdir, filtered=False,
+ force_mtime=None, fileobj=None,
+ compression_format="alone"):
+ for _ in tar_lzma_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj,
+ compression_format):
+ pass
=== modified file 'bzrlib/export/zip_exporter.py'
--- a/bzrlib/export/zip_exporter.py 2011-04-30 00:08:00 +0000
+++ b/bzrlib/export/zip_exporter.py 2011-06-07 13:33:41 +0000
@@ -44,7 +44,8 @@
_DIR_ATTR = stat.S_IFDIR | ZIP_DIRECTORY_BIT | DIR_PERMISSIONS
-def zip_exporter(tree, dest, root, subdir=None, filtered=False, force_mtime=None):
+def zip_exporter_generator(tree, dest, root, subdir=None, filtered=False,
+ force_mtime=None, fileobj=None):
""" Export this tree to a new zip file.
`dest` will be created holding the contents of this tree; if it
@@ -52,7 +53,9 @@
"""
compression = zipfile.ZIP_DEFLATED
- if dest == "-":
+ if fileobj is not None:
+ dest = fileobj
+ elif dest == "-":
dest = sys.stdout
zipf = zipfile.ZipFile(dest, "w", compression)
try:
@@ -100,6 +103,7 @@
zinfo.compress_type = compression
zinfo.external_attr = _FILE_ATTR
zipf.writestr(zinfo, tree.get_symlink_target(file_id))
+ yield
zipf.close()
@@ -108,3 +112,10 @@
os.remove(dest)
from bzrlib.errors import BzrError
raise BzrError("Can't export non-ascii filenames to zip")
+
+
+def zip_exporter(tree, dest, root, subdir=None, filtered=False,
+ force_mtime=None, fileobj=None):
+ for _ in zip_exporter_generator(tree, dest, root, subdir, filtered,
+ force_mtime, fileobj):
+ pass
=== modified file 'bzrlib/tests/blackbox/test_export.py'
--- a/bzrlib/tests/blackbox/test_export.py 2011-05-13 12:51:05 +0000
+++ b/bzrlib/tests/blackbox/test_export.py 2011-06-07 13:33:41 +0000
@@ -174,8 +174,8 @@
def run_tar_export_disk_and_stdout(self, extension, tarfile_flags):
tree = self.make_basic_tree()
fname = 'test.%s' % (extension,)
+ self.run_bzr('export -d tree %s' % (fname,))
mode = 'r|%s' % (tarfile_flags,)
- self.run_bzr('export -d tree %s' % (fname,))
ball = tarfile.open(fname, mode=mode)
self.assertTarANameAndContent(ball, root='test/')
content = self.run_bzr('export -d tree --format=%s -' % (extension,))[0]
=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- a/doc/en/release-notes/bzr-2.4.txt 2011-06-07 08:20:21 +0000
+++ b/doc/en/release-notes/bzr-2.4.txt 2011-06-07 17:21:50 +0000
@@ -785,6 +785,9 @@
(``bzrlib.working_tree.format_registry``) rather than using the class
methods on ``WorkingTreeFormat``. (Jelmer Vernooij, #714730)
+* Exporting may now be done with a generator
+ (``bzrlib.export.get_export_generator``) (Geoff/xaav, #791005)
+
Internals
*********
=== modified file 'doc/en/whats-new/whats-new-in-2.4.txt'
--- a/doc/en/whats-new/whats-new-in-2.4.txt 2011-05-27 15:02:17 +0000
+++ b/doc/en/whats-new/whats-new-in-2.4.txt 2011-06-06 17:08:37 +0000
@@ -101,6 +101,12 @@
network roundtrips. Other operations where a local branch is stacked on a
branch hosted on a smart server will also benefit.
+More export control
+*******************
+
+When exporting a tree, you may now use get_export_generator() to
+do an operation after each file is exported.
+
Testing
*******
More information about the bazaar-commits
mailing list