Rev 4740: (mbp) give a clearer warning about cross-format conversions earlier in fetch in file:///home/pqm/archives/thelove/bzr/2.0/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Wed Mar 17 05:37:42 GMT 2010


At file:///home/pqm/archives/thelove/bzr/2.0/

------------------------------------------------------------
revno: 4740 [merge]
revision-id: pqm at pqm.ubuntu.com-20100317053740-vics0asi5dga6bxy
parent: pqm at pqm.ubuntu.com-20100303102830-65cu66torg2offly
parent: mbp at canonical.com-20100317042648-hlt8lup7l8js5kny
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.0
timestamp: Wed 2010-03-17 05:37:40 +0000
message:
  (mbp) give a clearer warning about cross-format conversions earlier in fetch
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/smart/repository.py     repository.py-20061128022038-vr5wy5bubyb8xttk-1
  bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
  bzrlib/tests/test_ui.py        test_ui.py-20051130162854-458e667a7414af09
  bzrlib/ui/__init__.py          ui.py-20050824083933-8cf663c763ba53a9
  bzrlib/ui/text.py              text.py-20051130153916-2e438cffc8afc478
  bzrlib/upgrade.py              history2weaves.py-20050818063535-e7d319791c19a8b2
=== modified file 'NEWS'
--- a/NEWS	2010-03-03 09:21:47 +0000
+++ b/NEWS	2010-03-17 04:26:48 +0000
@@ -29,6 +29,12 @@
   a lock.
   (Martin Pool, #185103)
 
+* Give the warning about potentially slow cross-format fetches much
+  earlier on in the fetch operation.  Don't show this message during
+  upgrades, and show the correct format indication for remote
+  repositories.
+  (Martin Pool, #456077, #515356, #513157)
+
 * Handle renames correctly when there are files or directories that 
   differ only in case.  (Chris Jones, Martin Pool, #368931)
 

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2010-01-14 07:34:37 +0000
+++ b/bzrlib/repository.py	2010-02-25 04:31:05 +0000
@@ -3067,8 +3067,8 @@
     # Does the repository inventory storage understand references to trees?
     supports_tree_reference = None
 
-    def __str__(self):
-        return "<%s>" % self.__class__.__name__
+    def __repr__(self):
+        return "%s()" % self.__class__.__name__
 
     def __eq__(self, other):
         # format objects are generally stateless
@@ -3407,6 +3407,11 @@
         :return: None.
         """
         from bzrlib.fetch import RepoFetcher
+        # See <https://launchpad.net/bugs/456077> asking for a warning here
+        if self.source._format.network_name() != self.target._format.network_name():
+            ui.ui_factory.show_user_warning('cross_format_fetch',
+                from_format=self.source._format,
+                to_format=self.target._format)
         f = RepoFetcher(to_repository=self.target,
                                from_repository=self.source,
                                last_revision=revision_id,
@@ -3980,18 +3985,17 @@
         """See InterRepository.fetch()."""
         if fetch_spec is not None:
             raise AssertionError("Not implemented yet...")
-        # See <https://launchpad.net/bugs/456077> asking for a warning here
-        #
-        # nb this is only active for local-local fetches; other things using
-        # streaming.
-        ui.ui_factory.warn_cross_format_fetch(self.source._format,
-            self.target._format)
         if (not self.source.supports_rich_root()
             and self.target.supports_rich_root()):
             self._converting_to_rich_root = True
             self._revision_id_to_root_id = {}
         else:
             self._converting_to_rich_root = False
+        # See <https://launchpad.net/bugs/456077> asking for a warning here
+        if self.source._format.network_name() != self.target._format.network_name():
+            ui.ui_factory.show_user_warning('cross_format_fetch',
+                from_format=self.source._format,
+                to_format=self.target._format)
         revision_ids = self.target.search_missing_revision_ids(self.source,
             revision_id, find_ghosts=find_ghosts).get_keys()
         if not revision_ids:
@@ -4284,8 +4288,6 @@
                     self._extract_and_insert_inventories(
                         substream, src_serializer)
             elif substream_type == 'inventory-deltas':
-                ui.ui_factory.warn_cross_format_fetch(src_format,
-                    self.target_repo._format)
                 self._extract_and_insert_inventory_deltas(
                     substream, src_serializer)
             elif substream_type == 'chk_bytes':

=== modified file 'bzrlib/smart/repository.py'
--- a/bzrlib/smart/repository.py	2010-01-14 07:34:37 +0000
+++ b/bzrlib/smart/repository.py	2010-02-24 06:46:13 +0000
@@ -503,13 +503,6 @@
     yield pack_writer.begin()
     yield pack_writer.bytes_record(src_format.network_name(), '')
     for substream_type, substream in stream:
-        if substream_type == 'inventory-deltas':
-            # This doesn't feel like the ideal place to issue this warning;
-            # however we don't want to do it in the Repository that's
-            # generating the stream, because that might be on the server.
-            # Instead we try to observe it as the stream goes by.
-            ui.ui_factory.warn_cross_format_fetch(src_format,
-                '(remote)')
         for record in substream:
             if record.storage_kind in ('chunked', 'fulltext'):
                 serialised = record_to_fulltext_bytes(record)

=== modified file 'bzrlib/tests/blackbox/test_branch.py'
--- a/bzrlib/tests/blackbox/test_branch.py	2009-08-20 12:30:49 +0000
+++ b/bzrlib/tests/blackbox/test_branch.py	2010-02-24 08:03:07 +0000
@@ -326,6 +326,8 @@
             '  Packs 5 (adds stacking support, requires bzr 1.6)\n'
             'Source branch format does not support stacking, using format:\n'
             '  Branch format 7\n'
+            'Doing on-the-fly conversion from RepositoryFormatKnitPack1() to RepositoryFormatKnitPack5().\n'
+            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
             'Created new stacked branch referring to %s.\n' % (trunk.base,),
             err)
 
@@ -339,6 +341,8 @@
             '  Packs 5 rich-root (adds stacking support, requires bzr 1.6.1)\n'
             'Source branch format does not support stacking, using format:\n'
             '  Branch format 7\n'
+            'Doing on-the-fly conversion from RepositoryFormatKnitPack4() to RepositoryFormatKnitPack5RichRoot().\n'
+            'This may take some time. Upgrade the repositories to the same format for better performance.\n'
             'Created new stacked branch referring to %s.\n' % (trunk.base,),
             err)
 

=== modified file 'bzrlib/tests/test_ui.py'
--- a/bzrlib/tests/test_ui.py	2009-08-03 05:54:52 +0000
+++ b/bzrlib/tests/test_ui.py	2010-02-25 05:46:32 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2008, 2009 Canonical Ltd
+# Copyright (C) 2005, 2008, 2009, 2010 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -25,6 +25,8 @@
 
 from bzrlib import (
     errors,
+    remote,
+    repository,
     tests,
     ui as _mod_ui,
     )
@@ -300,6 +302,32 @@
         finally:
             pb.finished()
 
+    def test_text_ui_show_user_warning(self):
+        from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
+        from bzrlib.repofmt.pack_repo import RepositoryFormatKnitPack5
+        err = StringIO()
+        out = StringIO()
+        ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
+        remote_fmt = remote.RemoteRepositoryFormat()
+        remote_fmt._network_name = RepositoryFormatKnitPack5().network_name()
+        ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
+            to_format=remote_fmt)
+        self.assertEquals('', out.getvalue())
+        self.assertEquals("Doing on-the-fly conversion from RepositoryFormat2a() to "
+            "RemoteRepositoryFormat(_network_name='Bazaar RepositoryFormatKnitPack5 "
+            "(bzr 1.6)\\n').\nThis may take some time. Upgrade the repositories to "
+            "the same format for better performance.\n",
+            err.getvalue())
+        # and now with it suppressed please
+        err = StringIO()
+        out = StringIO()
+        ui = tests.TextUIFactory(stdin=None, stdout=out, stderr=err)
+        ui.suppressed_warnings.add('cross_format_fetch')
+        ui.show_user_warning('cross_format_fetch', from_format=RepositoryFormat2a(),
+            to_format=remote_fmt)
+        self.assertEquals('', out.getvalue())
+        self.assertEquals('', err.getvalue())
+
 
 class CLIUITests(TestCase):
 

=== modified file 'bzrlib/ui/__init__.py'
--- a/bzrlib/ui/__init__.py	2010-01-15 02:41:11 +0000
+++ b/bzrlib/ui/__init__.py	2010-02-25 06:02:41 +0000
@@ -105,10 +105,22 @@
 
     This tells the library how to display things to the user.  Through this
     layer different applications can choose the style of UI.
+
+    :ivar suppressed_warnings: Identifiers for user warnings that should 
+        no be emitted.
     """
 
+    _user_warning_templates = dict(
+        cross_format_fetch=("Doing on-the-fly conversion from "
+            "%(from_format)s to %(to_format)s.\n"
+            "This may take some time. Upgrade the repositories to the "
+            "same format for better performance."
+            )
+        )
+
     def __init__(self):
         self._task_stack = []
+        self.suppressed_warnings = set()
 
     def get_password(self, prompt='', **kwargs):
         """Prompt the user for a password.
@@ -170,6 +182,21 @@
         """
         pass
 
+    def format_user_warning(self, warning_id, message_args):
+        try:
+            template = self._user_warning_templates[warning_id]
+        except KeyError:
+            fail = "failed to format warning %r, %r" % (warning_id, message_args)
+            warnings.warn(fail)   # so tests will fail etc
+            return fail
+        try:
+            return template % message_args
+        except ValueError, e:
+            fail = "failed to format warning %r, %r: %s" % (
+                warning_id, message_args, e)
+            warnings.warn(fail)   # so tests will fail etc
+            return fail
+
     def get_boolean(self, prompt):
         """Get a boolean question answered from the user.
 
@@ -190,8 +217,11 @@
     def recommend_upgrade(self,
         current_format_name,
         basedir):
-        # this should perhaps be in the TextUIFactory and the default can do
+        # XXX: this should perhaps be in the TextUIFactory and the default can do
         # nothing
+        #
+        # XXX: Change to show_user_warning - that will accomplish the previous
+        # xxx. -- mbp 2010-02-25
         trace.warning("%s is deprecated "
             "and a better format is available.\n"
             "It is recommended that you upgrade by "
@@ -208,13 +238,32 @@
         """
         pass
 
+    def show_user_warning(self, warning_id, **message_args):
+        """Show a warning to the user.
+
+        This is specifically for things that are under the user's control (eg
+        outdated formats), not for internal program warnings like deprecated
+        APIs.
+
+        This can be overridden by UIFactory subclasses to show it in some 
+        appropriate way; the default UIFactory is noninteractive and does
+        nothing.  format_user_warning maps it to a string, though other
+        presentations can be used for particular UIs.
+
+        :param warning_id: An identifier like 'cross_format_fetch' used to 
+            check if the message is suppressed and to look up the string.
+        :param message_args: Arguments to be interpolated into the message.
+        """
+        pass
+
     def warn_cross_format_fetch(self, from_format, to_format):
-        """Warn about a potentially slow cross-format transfer"""
-        # See <https://launchpad.net/bugs/456077> asking for a warning here
-        trace.warning("Doing on-the-fly conversion from %s to %s.\n"
-            "This may take some time. Upgrade the repositories to the "
-            "same format for better performance.\n" %
-            (from_format, to_format))
+        """Warn about a potentially slow cross-format transfer.
+        
+        This is deprecated in favor of show_user_warning, but retained for api
+        compatibility in 2.0 and 2.1.
+        """
+        self.show_user_warning('cross_format_fetch', from_format=from_format,
+            to_format=to_format)
 
 
 class CLIUIFactory(UIFactory):

=== modified file 'bzrlib/ui/text.py'
--- a/bzrlib/ui/text.py	2009-08-06 02:23:37 +0000
+++ b/bzrlib/ui/text.py	2010-02-25 05:46:32 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2008, 2009 Canonical Ltd
+# Copyright (C) 2005, 2008, 2009, 2010 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -31,6 +31,7 @@
     progress,
     osutils,
     symbol_versioning,
+    trace,
     )
 
 """)
@@ -190,6 +191,18 @@
     def _progress_all_finished(self):
         self._progress_view.clear()
 
+    def show_user_warning(self, warning_id, **message_args):
+        """Show a text message to the user.
+
+        Explicitly not for warnings about bzr apis, deprecations or internals.
+        """
+        # eventually trace.warning should migrate here, to avoid logging and
+        # be easier to test; that has a lot of test fallout so for now just
+        # new code can call this
+        if warning_id not in self.suppressed_warnings:
+            self.stderr.write(self.format_user_warning(warning_id, message_args) +
+                '\n')
+
 
 class TextProgressView(object):
     """Display of progress bar and other information on a tty.

=== modified file 'bzrlib/upgrade.py'
--- a/bzrlib/upgrade.py	2009-05-07 05:08:46 +0000
+++ b/bzrlib/upgrade.py	2010-02-25 05:46:32 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2008, 2009 Canonical Ltd
+# Copyright (C) 2005, 2008, 2009, 2010 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -29,6 +29,9 @@
     def __init__(self, url, format=None):
         self.format = format
         self.bzrdir = BzrDir.open_unsupported(url)
+        # XXX: Change to cleanup
+        warning_id = 'cross_format_fetch'
+        saved_warning = warning_id in ui.ui_factory.suppressed_warnings
         if isinstance(self.bzrdir, RemoteBzrDir):
             self.bzrdir._ensure_real()
             self.bzrdir = self.bzrdir._real_bzrdir
@@ -36,10 +39,13 @@
             raise errors.UpgradeReadonly
         self.transport = self.bzrdir.root_transport
         self.pb = ui.ui_factory.nested_progress_bar()
+        ui.ui_factory.suppressed_warnings.add(warning_id)
         try:
             self.convert()
         finally:
             self.pb.finished()
+            if not saved_warning:
+                ui.ui_factory.suppressed_warnings.remove(warning_id)
 
     def convert(self):
         try:




More information about the bazaar-commits mailing list