Rev 4934: (jam) Add -Dbytes and log how many bytes are transferred for in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Jan 5 16:55:14 GMT 2010
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4934 [merge]
revision-id: pqm at pqm.ubuntu.com-20100105165512-ip2jyuy8f999raxm
parent: pqm at pqm.ubuntu.com-20100105045349-91sjr8vmex9iy8ex
parent: john at arbash-meinel.com-20100105155228-jm4mtt4gobh089xl
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2010-01-05 16:55:12 +0000
message:
(jam) Add -Dbytes and log how many bytes are transferred for
operations.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/help_topics/en/debug-flags.txt debugflags.txt-20090312050229-rdspqbqq4fzbjtpe-1
bzrlib/tests/per_uifactory/__init__.py __init__.py-20090923045301-o12zypjwsidxn2hy-1
bzrlib/ui/__init__.py ui.py-20050824083933-8cf663c763ba53a9
bzrlib/ui/text.py text.py-20051130153916-2e438cffc8afc478
=== modified file 'NEWS'
--- a/NEWS 2010-01-05 04:08:35 +0000
+++ b/NEWS 2010-01-05 16:55:12 +0000
@@ -17,16 +17,21 @@
New Features
************
+* ``bzr update`` now takes a ``--revision`` argument. This lets you
+ change the revision of the working tree to any revision in the
+ ancestry of the current or master branch. (Matthieu Moy, Mark Hammond,
+ Martin Pool, #45719)
+
+* ``-Dbytes`` can now be used to display the total number of bytes
+ transferred for the current command. This information is always logged
+ to ``.bzr.log`` for later inspection. (John Arbash Meinel)
+
* The ``suppress_warnings`` configuration option has been introduced and
accept the ``format_deprecation`` value to disable the corresponding
warning for repositories. It can be set to in either ``bazaar.conf``,
``locations.conf`` or ``branch.conf``.
(Ted Gould, Matthew Fuller, Vincent Ladeuil)
-* ``bzr update`` now takes a ``--revision`` argument. This lets you
- change the revision of the working tree to any revision in the
- ancestry of the current or master branch. (Matthieu Moy, Mark Hammond,
- Martin Pool, #45719)
Bug Fixes
*********
=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py 2009-12-09 05:47:32 +0000
+++ b/bzrlib/commands.py 2009-12-18 17:59:58 +0000
@@ -1103,6 +1103,8 @@
raise errors.BzrError("argv should be list of unicode strings.")
argv = new_argv
ret = run_bzr_catch_errors(argv)
+ bzrlib.ui.ui_factory.log_transport_activity(
+ display=('bytes' in debug.debug_flags))
trace.mutter("return code %d", ret)
osutils.report_extension_load_failures()
return ret
=== modified file 'bzrlib/help_topics/en/debug-flags.txt'
--- a/bzrlib/help_topics/en/debug-flags.txt 2009-12-22 04:07:36 +0000
+++ b/bzrlib/help_topics/en/debug-flags.txt 2010-01-05 04:30:07 +0000
@@ -5,6 +5,7 @@
prefix) put in the ``debug_flags`` variable in ``bazaar.conf``.
-Dauth Trace authentication sections used.
+-Dbytes Print out how many bytes were transferred
-Ddirstate Trace dirstate activity (verbose!)
-Derror Instead of normal error handling, always print a traceback
on error.
=== modified file 'bzrlib/tests/per_uifactory/__init__.py'
--- a/bzrlib/tests/per_uifactory/__init__.py 2009-11-16 01:18:03 +0000
+++ b/bzrlib/tests/per_uifactory/__init__.py 2010-01-05 15:52:28 +0000
@@ -39,6 +39,7 @@
from bzrlib import (
tests,
+ transport,
ui,
)
@@ -83,6 +84,24 @@
raise tests.TestSkipped(str(e))
output_stream.write('hello!')
+ def test_transport_activity(self):
+ # It doesn't matter what the implementation does, we just want to make
+ # sure the interface is there
+ t = transport.get_transport('memory:///')
+ self.factory.report_transport_activity(t, 1000, 'write')
+ self.factory.report_transport_activity(t, 2000, 'read')
+ self.factory.report_transport_activity(t, 4000, None)
+ self.factory.log_transport_activity()
+ self._check_log_transport_activity_noarg()
+ self.factory.log_transport_activity(display=True)
+ self._check_log_transport_activity_display()
+
+ def test_no_transport_activity(self):
+ # No activity to report
+ t = transport.get_transport('memory:///')
+ self.factory.log_transport_activity(display=True)
+ self._check_log_transport_activity_display_no_bytes()
+
class TestTextUIFactory(tests.TestCase, UIFactoryTestMixin):
@@ -113,6 +132,62 @@
self.stderr.getvalue())
self.assertEquals("", self.stdout.getvalue())
+ def _check_log_transport_activity_noarg(self):
+ self.assertEqual('', self.stdout.getvalue())
+ self.assertContainsRe(self.stderr.getvalue(), r'\d+KB\s+\dKB/s |')
+ self.assertNotContainsRe(self.stderr.getvalue(), r'Transferred:')
+
+ def _check_log_transport_activity_display(self):
+ self.assertEqual('', self.stdout.getvalue())
+ # Without a TTY, we shouldn't display anything
+ self.assertEqual('', self.stderr.getvalue())
+
+ def _check_log_transport_activity_display_no_bytes(self):
+ self.assertEqual('', self.stdout.getvalue())
+ # Without a TTY, we shouldn't display anything
+ self.assertEqual('', self.stderr.getvalue())
+
+
+class TestTTYTextUIFactory(TestTextUIFactory):
+
+ def setUp(self):
+ super(TestTTYTextUIFactory, self).setUp()
+
+ class TTYStringIO(object):
+ """Thunk over to StringIO() for everything but 'isatty'"""
+
+ def __init__(self):
+ self.__dict__['_sio'] = StringIO()
+
+ def isatty(self):
+ return True
+
+ def __getattr__(self, name):
+ return getattr(self._sio, name)
+
+ def __setattr__(self, name, value):
+ return setattr(self._sio, name, value)
+
+ # Remove 'TERM' == 'dumb' which causes us to *not* treat output as a
+ # real terminal, even though isatty returns True
+ self._captureVar('TERM', None)
+ self.stderr = TTYStringIO()
+ self.stdout = TTYStringIO()
+ self.factory = ui.text.TextUIFactory(self.stdin, self.stdout,
+ self.stderr)
+
+ def _check_log_transport_activity_display(self):
+ self.assertEqual('', self.stdout.getvalue())
+ # Displaying the result should write to the progress stream
+ self.assertContainsRe(self.stderr.getvalue(),
+ r'Transferred: 7KiB'
+ r' \(\d+\.\dK/s r:2K w:1K u:4K\)')
+
+ def _check_log_transport_activity_display_no_bytes(self):
+ self.assertEqual('', self.stdout.getvalue())
+ # Without actual bytes transferred, we should report nothing
+ self.assertEqual('', self.stderr.getvalue())
+
class TestSilentUIFactory(tests.TestCase, UIFactoryTestMixin):
# discards output, therefore tests for output expect nothing
@@ -134,6 +209,15 @@
def _check_show_warning(self, msg):
pass
+ def _check_log_transport_activity_noarg(self):
+ pass
+
+ def _check_log_transport_activity_display(self):
+ pass
+
+ def _check_log_transport_activity_display_no_bytes(self):
+ pass
+
class TestCannedInputUIFactory(tests.TestCase, UIFactoryTestMixin):
# discards output, reads input from variables
@@ -154,4 +238,11 @@
def _check_show_warning(self, msg):
pass
-
+ def _check_log_transport_activity_noarg(self):
+ pass
+
+ def _check_log_transport_activity_display(self):
+ pass
+
+ def _check_log_transport_activity_display_no_bytes(self):
+ pass
=== modified file 'bzrlib/ui/__init__.py'
--- a/bzrlib/ui/__init__.py 2009-12-10 16:54:28 +0000
+++ b/bzrlib/ui/__init__.py 2009-12-18 16:39:21 +0000
@@ -246,6 +246,19 @@
"""
pass
+ def log_transport_activity(self, display=False):
+ """Write out whatever transport activity has been measured.
+
+ Implementations are allowed to do nothing, but it is useful if they can
+ write a line to the log file.
+
+ :param display: If False, only log to disk, if True also try to display
+ a message to the user.
+ :return: None
+ """
+ # Default implementation just does nothing
+ pass
+
def show_error(self, msg):
"""Show an error message (not an exception) to the user.
@@ -345,3 +358,6 @@
def show_transport_activity(self, transport, direction, byte_count):
pass
+
+ def log_transport_activity(self, display=False):
+ pass
=== modified file 'bzrlib/ui/text.py'
--- a/bzrlib/ui/text.py 2009-12-22 04:07:36 +0000
+++ b/bzrlib/ui/text.py 2010-01-05 04:30:07 +0000
@@ -32,6 +32,7 @@
progress,
osutils,
symbol_versioning,
+ trace,
)
""")
@@ -203,6 +204,12 @@
self._progress_view.show_transport_activity(transport,
direction, byte_count)
+ def log_transport_activity(self, display=False):
+ """See UIFactory.log_transport_activity()"""
+ log = getattr(self._progress_view, 'log_transport_activity', None)
+ if log is not None:
+ log(display=display)
+
def show_error(self, msg):
self.clear_term()
self.stderr.write("bzr: error: %s\n" % msg)
@@ -257,6 +264,8 @@
self._last_task = None
self._total_byte_count = 0
self._bytes_since_update = 0
+ self._bytes_by_direction = {'unknown': 0, 'read': 0, 'write': 0}
+ self._first_byte_time = None
self._fraction = 0
# force the progress bar to be off, as at the moment it doesn't
# correspond reliably to overall command progress
@@ -369,17 +378,25 @@
This may update a progress bar, spinner, or similar display.
By default it does nothing.
"""
- # XXX: Probably there should be a transport activity model, and that
- # too should be seen by the progress view, rather than being poked in
- # here.
+ # XXX: there should be a transport activity model, and that too should
+ # be seen by the progress view, rather than being poked in here.
+ self._total_byte_count += byte_count
+ self._bytes_since_update += byte_count
+ if self._first_byte_time is None:
+ # Note that this isn't great, as technically it should be the time
+ # when the bytes started transferring, not when they completed.
+ # However, we usually start with a small request anyway.
+ self._first_byte_time = time.time()
+ if direction in self._bytes_by_direction:
+ self._bytes_by_direction[direction] += byte_count
+ else:
+ self._bytes_by_direction['unknown'] += byte_count
if 'no_activity' in debug.debug_flags:
# Can be used as a workaround if
# <https://launchpad.net/bugs/321935> reappears and transport
# activity is cluttering other output. However, thanks to
# TextUIOutputStream this shouldn't be a problem any more.
return
- self._total_byte_count += byte_count
- self._bytes_since_update += byte_count
now = time.time()
if self._total_byte_count < 2000:
# a little resistance at first, so it doesn't stay stuck at 0
@@ -399,6 +416,37 @@
self._last_transport_msg = msg
self._repaint()
+ def _format_bytes_by_direction(self):
+ if self._first_byte_time is None:
+ bps = 0.0
+ else:
+ transfer_time = time.time() - self._first_byte_time
+ if transfer_time < 0.001:
+ transfer_time = 0.001
+ bps = self._total_byte_count / transfer_time
+
+ msg = ('Transferred: %.0fKiB'
+ ' (%.1fK/s r:%.0fK w:%.0fK'
+ % (self._total_byte_count / 1024.,
+ bps / 1024.,
+ self._bytes_by_direction['read'] / 1024.,
+ self._bytes_by_direction['write'] / 1024.,
+ ))
+ if self._bytes_by_direction['unknown'] > 0:
+ msg += ' u:%.0fK)' % (
+ self._bytes_by_direction['unknown'] / 1024.
+ )
+ else:
+ msg += ')'
+ return msg
+
+ def log_transport_activity(self, display=False):
+ msg = self._format_bytes_by_direction()
+ trace.mutter(msg)
+ if display and self._total_byte_count > 0:
+ self.clear()
+ self._term_file.write(msg + '\n')
+
class TextUIOutputStream(object):
"""Decorates an output stream so that the terminal is cleared before writing.
More information about the bazaar-commits
mailing list