← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:codehosting-breezy into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:codehosting-breezy into launchpad:master.

Commit message:
Port codehosting to Breezy

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/373805

Most of this is relatively mechanical: bzrlib imports become breezy imports, some things move around a little more (mainly to breezy.bzr), bzrdir becomes controldir in many cases, I tightened up some bytes/text handling, and there were a couple of other minor API changes.

Due to problems with subvertpy, codeimport remains on Bazaar for now.  This entails some fiddly code to allow Bazaar and Breezy to coexist in the same codebase.

DirectBranchCommit.commit needs a new call to self.transform_preview.fixup_new_roots.  I think this may technically have been needed by Bazaar too, since bzrlib.transform._alter_files calls it, but it no longer seems to be possible to get away without it.

We have to explicitly initialize Breezy in lib/lp/codehosting/__init__.py, as otherwise it initializes itself with a terminal-oriented UI, causing some unexpected output to appear in logs.

We have to disable some plugins that are now built into Breezy and likely to cause trouble if invoked, although unfortunately we have no very elegant way to do that.  cvs, darcs, email, and mtn are disabled using BRZ_DISABLE_PLUGINS.  git requires more work: we can't allow Breezy to even import this until codeimport is also ported, since it requires a newer version of dulwich which is incompatible with bzr-git (and that isn't particularly straightforward to fix), so I ended up stubbing it in sys.modules so that importing it has no effect.  Fortunately Breezy currently only imports breezy.git and relies on it to register its own formats, so this crude strategy works.

The hack in scripts/mirror-branch.py to force bzr to use urllib is no longer required: Breezy removed pycurl support.

This is essentially the same as https://code.launchpad.net/~cjwatson/launchpad/codehosting-breezy/+merge/373020, converted to git and rebased on master.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:codehosting-breezy into launchpad:master.
diff --git a/Makefile b/Makefile
index 62d59e2..0fc97c2 100644
--- a/Makefile
+++ b/Makefile
@@ -306,10 +306,10 @@ run_all: build inplace stop
 	memcached,rabbitmq -i $(LPCONFIG)
 
 run_codebrowse: compile
-	BZR_PLUGIN_PATH=bzrplugins $(PY) scripts/start-loggerhead.py
+	BRZ_PLUGIN_PATH=brzplugins $(PY) scripts/start-loggerhead.py
 
 start_codebrowse: compile
-	BZR_PLUGIN_PATH=$(shell pwd)/bzrplugins $(PY) scripts/start-loggerhead.py --daemon
+	BRZ_PLUGIN_PATH=$(shell pwd)/brzplugins $(PY) scripts/start-loggerhead.py --daemon
 
 stop_codebrowse:
 	$(PY) scripts/stop-loggerhead.py
diff --git a/brzplugins/builder b/brzplugins/builder
new file mode 120000
index 0000000..2877987
--- /dev/null
+++ b/brzplugins/builder
@@ -0,0 +1 @@
+../sourcecode/brz-builder/brzbuildrecipe
\ No newline at end of file
diff --git a/brzplugins/difftacular b/brzplugins/difftacular
new file mode 120000
index 0000000..e34dfd2
--- /dev/null
+++ b/brzplugins/difftacular
@@ -0,0 +1 @@
+../sourcecode/difftacular
\ No newline at end of file
diff --git a/brzplugins/loom b/brzplugins/loom
new file mode 120000
index 0000000..ed0b36f
--- /dev/null
+++ b/brzplugins/loom
@@ -0,0 +1 @@
+../sourcecode/brz-loom
\ No newline at end of file
diff --git a/bzrplugins/lpserve/__init__.py b/brzplugins/lpserve/__init__.py
similarity index 97%
rename from bzrplugins/lpserve/__init__.py
rename to brzplugins/lpserve/__init__.py
index 5ea5f86..a0b3cd5 100644
--- a/bzrplugins/lpserve/__init__.py
+++ b/brzplugins/lpserve/__init__.py
@@ -28,7 +28,7 @@ import tempfile
 import threading
 import time
 
-from bzrlib import (
+from breezy import (
     commands,
     errors,
     lockdir,
@@ -36,15 +36,15 @@ from bzrlib import (
     trace,
     ui,
     )
-from bzrlib.commands import (
+from breezy.commands import (
     Command,
     register_command,
     )
-from bzrlib.option import (
+from breezy.option import (
     Option,
     RegistryOption,
     )
-from bzrlib.transport import (
+from breezy.transport import (
     get_transport,
     transport_server_registry,
     )
@@ -88,7 +88,7 @@ class cmd_launchpad_server(Command):
             type=unicode),
         RegistryOption(
             'protocol', help="Protocol to serve.",
-            lazy_registry=('bzrlib.transport', 'transport_server_registry'),
+            lazy_registry=('breezy.transport', 'transport_server_registry'),
             value_switches=True),
         ]
 
@@ -192,7 +192,7 @@ class LPForkingService(object):
             that should be reset.
 
             fork-env allows you to supply environment variables such as
-            "BZR_EMAIL: joe@xxxxxxx" which will be set in os.environ before
+            "BRZ_EMAIL: joe@xxxxxxx" which will be set in os.environ before
             the command is run.
     """
 
@@ -301,9 +301,9 @@ class LPForkingService(object):
     #       don't know any way to *remove* a function registered via
     #       'atexit()' so if the forking service has some state, we my try to
     #       clean it up incorrectly.
-    #       Note that the bzr script itself uses sys.exitfunc(); os._exit() in
-    #       the 'bzr' main script, as the teardown time of all the python
-    #       state was quite noticeable in real-world runtime. As such, bzrlib
+    #       Note that the brz script itself uses sys.exitfunc(); os._exit() in
+    #       the 'brz' main script, as the teardown time of all the python
+    #       state was quite noticeable in real-world runtime. As such, breezy
     #       should be pretty safe, or it would have been failing for people
     #       already.
     # [Decision #7]
@@ -483,7 +483,7 @@ class LPForkingService(object):
         os.rmdir(base_path)
 
     def _bind_child_file_descriptors(self, base_path):
-        # Note: by this point bzrlib has opened stderr for logging
+        # Note: by this point breezy has opened stderr for logging
         # (as part of starting the service process in the first place).
         # As such, it has a stream handler that writes to stderr.
         # logging tries to flush and close that, but the file is already
@@ -975,16 +975,16 @@ register_command(cmd_launchpad_replay)
 # manually, and observe what was expensive to import.  It doesn't seem
 # very easy to get this right automatically.
 libraries_to_preload = [
-    'bzrlib.errors',
-    'bzrlib.repofmt.groupcompress_repo',
-    'bzrlib.repository',
-    'bzrlib.smart',
-    'bzrlib.smart.protocol',
-    'bzrlib.smart.request',
-    'bzrlib.smart.server',
-    'bzrlib.smart.vfs',
-    'bzrlib.transport.local',
-    'bzrlib.transport.readonly',
+    'breezy.bzr.groupcompress_repo',
+    'breezy.bzr.smart',
+    'breezy.bzr.smart.protocol',
+    'breezy.bzr.smart.request',
+    'breezy.bzr.smart.server',
+    'breezy.bzr.smart.vfs',
+    'breezy.errors',
+    'breezy.repository',
+    'breezy.transport.local',
+    'breezy.transport.readonly',
     'lp.codehosting.bzrutils',
     'lp.codehosting.vfs',
     'lp.codehosting.vfs.branchfs',
diff --git a/bzrplugins/lpserve/test_lpserve.py b/brzplugins/lpserve/test_lpserve.py
similarity index 92%
rename from bzrplugins/lpserve/test_lpserve.py
rename to brzplugins/lpserve/test_lpserve.py
index fd5baa7..be5c006 100644
--- a/bzrplugins/lpserve/test_lpserve.py
+++ b/brzplugins/lpserve/test_lpserve.py
@@ -11,18 +11,18 @@ import tempfile
 import threading
 import time
 
-from bzrlib import (
+from breezy import (
     errors,
     osutils,
     tests,
     trace,
     )
-from bzrlib.plugins import lpserve
+from breezy.plugins import lpserve
 from testtools import content
 
 from lp.codehosting import (
-    get_bzr_path,
-    get_BZR_PLUGIN_PATH_for_subprocess,
+    get_brz_path,
+    get_BRZ_PLUGIN_PATH_for_subprocess,
     )
 from lp.testing.fakemethod import FakeMethod
 
@@ -187,13 +187,13 @@ class TestLPForkingServiceParseEnv(tests.TestCase):
         self.assertEnv({}, 'end\n')
 
     def test_one_entries(self):
-        self.assertEnv({'BZR_EMAIL': 'joe@xxxxxxx'},
-                       'BZR_EMAIL: joe@xxxxxxx\n'
+        self.assertEnv({'BRZ_EMAIL': 'joe@xxxxxxx'},
+                       'BRZ_EMAIL: joe@xxxxxxx\n'
                        'end\n')
 
     def test_two_entries(self):
-        self.assertEnv({'BZR_EMAIL': 'joe@xxxxxxx', 'BAR': 'foo'},
-                       'BZR_EMAIL: joe@xxxxxxx\n'
+        self.assertEnv({'BRZ_EMAIL': 'joe@xxxxxxx', 'BAR': 'foo'},
+                       'BRZ_EMAIL: joe@xxxxxxx\n'
                        'BAR: foo\n'
                        'end\n')
 
@@ -201,10 +201,10 @@ class TestLPForkingServiceParseEnv(tests.TestCase):
         self.assertInvalid('')
 
     def test_invalid_end(self):
-        self.assertInvalid("BZR_EMAIL: joe@xxxxxxx\n")
+        self.assertInvalid("BRZ_EMAIL: joe@xxxxxxx\n")
 
     def test_invalid_entry(self):
-        self.assertInvalid("BZR_EMAIL joe@xxxxxxx\nend\n")
+        self.assertInvalid("BRZ_EMAIL joe@xxxxxxx\nend\n")
 
 
 class TestLPForkingService(TestCaseWithLPForkingService):
@@ -238,19 +238,19 @@ class TestLPForkingService(TestCaseWithLPForkingService):
     def test_send_fork_env_with_env(self):
         response = self.send_message_to_service(
             'fork-env rocks\n'
-            'BZR_EMAIL: joe@xxxxxxxxxxx\n'
+            'BRZ_EMAIL: joe@xxxxxxxxxxx\n'
             'end\n')
         self.assertEqual('ok\nfake forking\n', response)
-        self.assertEqual([(['rocks'], {'BZR_EMAIL': 'joe@xxxxxxxxxxx'})],
+        self.assertEqual([(['rocks'], {'BRZ_EMAIL': 'joe@xxxxxxxxxxx'})],
                          self.service.fork_log)
 
     def test_send_fork_env_slowly(self):
         response = self.send_message_to_service(
             'fork-env rocks\n'
-            'BZR_EMAIL: joe@xxxxxxxxxxx\n'
+            'BRZ_EMAIL: joe@xxxxxxxxxxx\n'
             'end\n', one_byte_at_a_time=True)
         self.assertEqual('ok\nfake forking\n', response)
-        self.assertEqual([(['rocks'], {'BZR_EMAIL': 'joe@xxxxxxxxxxx'})],
+        self.assertEqual([(['rocks'], {'BRZ_EMAIL': 'joe@xxxxxxxxxxx'})],
                          self.service.fork_log)
 
     def test_send_incomplete_fork_env_timeout(self):
@@ -258,7 +258,7 @@ class TestLPForkingService(TestCaseWithLPForkingService):
         # content
         response = self.send_message_to_service(
             'fork-env rocks\n'
-            'BZR_EMAIL: joe@xxxxxxxxxxx\n',
+            'BRZ_EMAIL: joe@xxxxxxxxxxx\n',
             one_byte_at_a_time=True)
         # Note that we *don't* send a final 'end\n'
         self.assertStartsWith(response, 'FAILURE\n')
@@ -315,24 +315,24 @@ class TestCaseWithSubprocess(tests.TestCaseWithTransport):
     The launchpad infrastructure requires a fair amount of configuration to
     get paths, etc correct. This provides a "start_bzr_subprocess" command
     that has all of those paths appropriately set, but otherwise functions the
-    same as the bzrlib.tests.TestCase version.
+    same as the breezy.tests.TestCase version.
     """
 
     def start_bzr_subprocess(self, process_args, env_changes=None,
                              working_dir=None):
         """Start bzr in a subprocess for testing.
 
-        Copied and modified from `bzrlib.tests.TestCase.start_bzr_subprocess`.
+        Copied and modified from `breezy.tests.TestCase.start_bzr_subprocess`.
         This version removes some of the skipping stuff, some of the
         irrelevant comments (e.g. about win32) and uses Launchpad's own
-        mechanisms for getting the path to 'bzr'.
+        mechanisms for getting the path to 'brz'.
 
         Comments starting with 'LAUNCHPAD' are comments about our
         modifications.
         """
         if env_changes is None:
             env_changes = {}
-        env_changes['BZR_PLUGIN_PATH'] = get_BZR_PLUGIN_PATH_for_subprocess()
+        env_changes['BRZ_PLUGIN_PATH'] = get_BRZ_PLUGIN_PATH_for_subprocess()
         old_env = {}
 
         def cleanup_environment():
@@ -348,12 +348,12 @@ class TestCaseWithSubprocess(tests.TestCaseWithTransport):
             cwd = osutils.getcwd()
             os.chdir(working_dir)
 
-        # LAUNCHPAD: We can't use self.get_bzr_path(), since it'll find
-        # lib/bzrlib, rather than the path to bin/bzr.
-        bzr_path = get_bzr_path()
+        # LAUNCHPAD: We can't use self.get_brz_path(), since it'll find
+        # lib/breezy, rather than the path to bin/brz.
+        brz_path = get_brz_path()
         try:
             cleanup_environment()
-            command = [bzr_path]
+            command = [brz_path]
             command.extend(process_args)
             process = self._popen(
                 command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
@@ -464,8 +464,8 @@ class TestCaseWithLPForkingServiceSubprocess(TestCaseWithSubprocess):
         # The service wants to create this file as a socket.
         os.remove(path)
         env_changes = {
-            'BZR_PLUGIN_PATH': lpserve.__path__[0],
-            'BZR_LOG': tempname,
+            'BRZ_PLUGIN_PATH': lpserve.__path__[0],
+            'BRZ_LOG': tempname,
             }
         proc = self._start_subprocess(path, env_changes)
         return proc, path
@@ -579,7 +579,7 @@ class TestLPServiceInSubprocess(TestCaseWithLPForkingServiceSubprocess):
 
     def test_fork_respects_env_vars(self):
         path, pid, sock = self.send_fork_request('whoami',
-            env={'BZR_EMAIL': 'this_test@xxxxxxxxxxx'})
+            env={'BRZ_EMAIL': 'this_test@xxxxxxxxxxx'})
         stdout_content, stderr_content = self.communicate_with_fork(path)
         self.assertEqual('', stderr_content)
         self.assertEqual('this_test@xxxxxxxxxxx\n', stdout_content)
diff --git a/bzrplugins/builder b/bzrplugins/builder
deleted file mode 120000
index 733b41e..0000000
--- a/bzrplugins/builder
+++ /dev/null
@@ -1 +0,0 @@
-../sourcecode/bzr-builder/
\ No newline at end of file
diff --git a/bzrplugins/difftacular b/bzrplugins/difftacular
deleted file mode 120000
index 7129510..0000000
--- a/bzrplugins/difftacular
+++ /dev/null
@@ -1 +0,0 @@
-../sourcecode/difftacular/
\ No newline at end of file
diff --git a/bzrplugins/loom b/bzrplugins/loom
deleted file mode 120000
index 68f0573..0000000
--- a/bzrplugins/loom
+++ /dev/null
@@ -1 +0,0 @@
-../sourcecode/bzr-loom
\ No newline at end of file
diff --git a/constraints.txt b/constraints.txt
index fa23f05..0bd51da 100644
--- a/constraints.txt
+++ b/constraints.txt
@@ -233,6 +233,8 @@ bcrypt==3.1.4
 BeautifulSoup==3.2.1
 beautifulsoup4[lxml]==4.7.1
 billiard==3.5.0.5
+bleach==3.1.0
+breezy==3.0.1
 bson==0.3.3
 # lp:~launchpad/bzr/lp
 bzr==2.6.0.lp.4
@@ -241,6 +243,7 @@ certifi==2019.3.9
 cffi==1.11.2
 Chameleon==2.11
 chardet==3.0.4
+configobj==5.0.6
 constantly==15.1.0
 cookies==2.2.1
 cryptography==2.7
@@ -257,6 +260,7 @@ elementtree==1.2.6-20050316
 enum34==1.1.6
 epydoc==3.0.1
 extras==1.0.0
+fastimport==0.9.8
 feedparser==5.2.1
 feedvalidator==0.0.0DEV-r1049
 fixtures==3.0.0
@@ -381,6 +385,7 @@ van.testing==3.0.0
 vine==1.1.4
 virtualenv-tools3==2.0.0
 wadllib==1.3.2
+webencodings==0.5.1
 wheel==0.29.0
 wsgiref==0.1.2
 z3c.pt==2.2.3
diff --git a/lib/launchpad_loggerhead/app.py b/lib/launchpad_loggerhead/app.py
index ce24213..cd98725 100644
--- a/lib/launchpad_loggerhead/app.py
+++ b/lib/launchpad_loggerhead/app.py
@@ -8,13 +8,13 @@ import urllib
 import urlparse
 import xmlrpclib
 
-from bzrlib import (
+from breezy import (
     errors,
     lru_cache,
     urlutils,
     )
-from bzrlib.transport import get_transport
-from bzrlib.url_policy_open import open_only_scheme
+from breezy.transport import get_transport
+from breezy.url_policy_open import open_only_scheme
 from loggerhead.apps import (
     favicon_app,
     static_app,
diff --git a/lib/launchpad_loggerhead/wsgi.py b/lib/launchpad_loggerhead/wsgi.py
index e8822b1..ca95aef 100644
--- a/lib/launchpad_loggerhead/wsgi.py
+++ b/lib/launchpad_loggerhead/wsgi.py
@@ -153,16 +153,16 @@ class LoggerheadApplication(Application):
         cfg.update(self.options)
         return cfg
 
-    def _load_bzr_plugins(self):
-        from bzrlib.plugin import load_plugins
+    def _load_brz_plugins(self):
+        from breezy.plugin import load_plugins
         load_plugins()
 
-        import bzrlib.plugins
-        if getattr(bzrlib.plugins, "loom", None) is None:
+        import breezy.plugins
+        if getattr(breezy.plugins, "loom", None) is None:
             log.error("Loom plugin loading failed.")
 
     def load(self):
-        self._load_bzr_plugins()
+        self._load_brz_plugins()
 
         with open(os.path.join(
                 config.root, config.codebrowse.secret_path)) as secret_file:
diff --git a/lib/lp/app/browser/stringformatter.py b/lib/lp/app/browser/stringformatter.py
index 1198a83..57b8eaf 100644
--- a/lib/lp/app/browser/stringformatter.py
+++ b/lib/lp/app/browser/stringformatter.py
@@ -21,7 +21,7 @@ from itertools import izip_longest
 import re
 import sys
 
-from bzrlib.patches import hunk_from_header
+from breezy.patches import hunk_from_header
 from lxml import html
 import markdown
 from zope.component import getUtility
diff --git a/lib/lp/code/browser/bazaar.py b/lib/lp/code/browser/bazaar.py
index 26b34dc..305c740 100644
--- a/lib/lp/code/browser/bazaar.py
+++ b/lib/lp/code/browser/bazaar.py
@@ -12,7 +12,7 @@ __all__ = [
 
 from datetime import datetime
 
-import bzrlib
+import breezy
 from zope.component import getUtility
 
 from lp.code.enums import CodeImportReviewStatus
@@ -51,8 +51,8 @@ class BazaarApplicationView(LaunchpadView):
             review_status=CodeImportReviewStatus.REVIEWED).count()
 
     @property
-    def bzr_version(self):
-        return bzrlib.__version__
+    def brz_version(self):
+        return breezy.__version__
 
     def _precacheViewPermissions(self, branches):
         """Precache the launchpad.View permissions on the branches."""
diff --git a/lib/lp/code/browser/sourcepackagerecipe.py b/lib/lp/code/browser/sourcepackagerecipe.py
index a16f29b..d712879 100644
--- a/lib/lp/code/browser/sourcepackagerecipe.py
+++ b/lib/lp/code/browser/sourcepackagerecipe.py
@@ -17,7 +17,7 @@ __all__ = [
 
 import itertools
 
-from bzrlib.plugins.builder.recipe import (
+from breezy.plugins.builder.recipe import (
     ForbiddenInstructionError,
     RecipeParseError,
     )
diff --git a/lib/lp/code/bzr.py b/lib/lp/code/bzr.py
index 10683e1..fe1a7d8 100644
--- a/lib/lp/code/bzr.py
+++ b/lib/lp/code/bzr.py
@@ -24,53 +24,53 @@ import lp.codehosting
 # Silence lint warning.
 lp.codehosting
 
-from bzrlib.branch import (
+from breezy.branch import UnstackableBranchFormat
+from breezy.bzr.branch import (
     BranchReferenceFormat,
     BzrBranchFormat6,
     BzrBranchFormat7,
     )
-from bzrlib.branchfmt.fullhistory import BzrBranchFormat5
-from bzrlib.bzrdir import (
+from breezy.bzr.bzrdir import (
     BzrDirMetaFormat1,
     BzrDirMetaFormat1Colo,
     )
-from bzrlib.errors import (
+from breezy.bzr.fullhistory import BzrBranchFormat5
+from breezy.bzr.groupcompress_repo import RepositoryFormat2a
+from breezy.bzr.knitpack_repo import (
+    RepositoryFormatKnitPack1,
+    RepositoryFormatKnitPack3,
+    RepositoryFormatKnitPack4,
+    RepositoryFormatKnitPack5,
+    )
+from breezy.bzr.knitrepo import (
+    RepositoryFormatKnit1,
+    RepositoryFormatKnit3,
+    RepositoryFormatKnit4,
+    )
+from breezy.errors import (
     NotStacked,
     NoSuchRevision,
-    UnstackableBranchFormat,
     )
-from bzrlib.plugins.loom.branch import (
+from breezy.plugins.loom.branch import (
     BzrBranchLoomFormat1,
     BzrBranchLoomFormat6,
     )
-from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
-from bzrlib.plugins.weave_fmt.bzrdir import (
+from breezy.plugins.weave_fmt.branch import BzrBranchFormat4
+from breezy.plugins.weave_fmt.bzrdir import (
     BzrDirFormat4,
     BzrDirFormat5,
     BzrDirFormat6,
     )
-from bzrlib.plugins.weave_fmt.repository import (
+from breezy.plugins.weave_fmt.repository import (
     RepositoryFormat4,
     RepositoryFormat5,
     RepositoryFormat6,
     RepositoryFormat7,
     )
-from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
-from bzrlib.repofmt.knitpack_repo import (
-    RepositoryFormatKnitPack1,
-    RepositoryFormatKnitPack3,
-    RepositoryFormatKnitPack4,
-    RepositoryFormatKnitPack5,
-    )
-from bzrlib.revision import (
+from breezy.revision import (
     is_null,
     NULL_REVISION,
     )
-from bzrlib.repofmt.knitrepo import (
-    RepositoryFormatKnit1,
-    RepositoryFormatKnit3,
-    RepositoryFormatKnit4,
-    )
 from lazr.enum import (
     DBEnumeratedType,
     DBItem,
@@ -305,7 +305,7 @@ def get_branch_formats(bzr_branch):
 
     :returns: tuple of (ControlFormat, BranchFormat, RepositoryFormat)
     """
-    control_string = bzr_branch.bzrdir._format.get_format_string()
+    control_string = bzr_branch.controldir._format.get_format_string()
     branch_string = bzr_branch._format.get_format_string()
     repository_string = bzr_branch.repository._format.get_format_string()
     return (ControlFormat.get_enum(control_string),
diff --git a/lib/lp/code/configure.zcml b/lib/lp/code/configure.zcml
index 0ae4a3c..0a3537e 100644
--- a/lib/lp/code/configure.zcml
+++ b/lib/lp/code/configure.zcml
@@ -1191,19 +1191,19 @@
        />
   </class>
   <class
-     class="bzrlib.plugins.builder.recipe.BaseRecipeBranch">
+     class="breezy.plugins.builder.recipe.BaseRecipeBranch">
     <allow attributes="name url revspec revid child_branches deb_version __str__" />
   </class>
   <class
-     class="bzrlib.plugins.builder.recipe.RecipeBranch">
+     class="breezy.plugins.builder.recipe.RecipeBranch">
     <allow attributes="name url revspec revid child_branches __str__" />
   </class>
   <class
-     class="bzrlib.plugins.builder.recipe.MergeInstruction">
+     class="breezy.plugins.builder.recipe.MergeInstruction">
     <allow attributes="as_tuple recipe_branch nest_path" />
   </class>
   <class
-     class="bzrlib.plugins.builder.recipe.NestInstruction">
+     class="breezy.plugins.builder.recipe.NestInstruction">
     <allow attributes="as_tuple recipe_branch nest_path" />
   </class>
 
diff --git a/lib/lp/code/errors.py b/lib/lp/code/errors.py
index 56521b5..f810475 100644
--- a/lib/lp/code/errors.py
+++ b/lib/lp/code/errors.py
@@ -66,7 +66,7 @@ __all__ = [
 
 import httplib
 
-from bzrlib.plugins.builder.recipe import RecipeParseError
+from breezy.plugins.builder.recipe import RecipeParseError
 from lazr.restful.declarations import error_status
 
 from lp.app.errors import (
diff --git a/lib/lp/code/interfaces/branch.py b/lib/lp/code/interfaces/branch.py
index 2d20376..29d5fdf 100644
--- a/lib/lp/code/interfaces/branch.py
+++ b/lib/lp/code/interfaces/branch.py
@@ -512,7 +512,7 @@ class IBranchView(IHasOwner, IHasBranchTarget, IHasMergeProposals,
 
         They are ordered with the most recent revision first, and the list
         only contains those in the "leftmost tree", or in other words
-        the revisions that match the revision history from bzrlib for this
+        the revisions that match the revision history from breezy for this
         branch.
 
         The revisions are listed as tuples of (`BranchRevision`, `Revision`).
@@ -719,7 +719,7 @@ class IBranchView(IHasOwner, IHasBranchTarget, IHasMergeProposals,
         """Construct a URL for this branch in codebrowse.
 
         :param extras: Zero or more path segments that will be joined onto the
-            end of the URL (with `bzrlib.urlutils.join`).
+            end of the URL (with `breezy.urlutils.join`).
         """
 
     browse_source_url = Attribute(
@@ -993,7 +993,7 @@ class IBranchView(IHasOwner, IHasBranchTarget, IHasMergeProposals,
         :return: tuple of three items.
             1. Ancestry set of bzr revision-ids.
             2. History list of bzr revision-ids. Similar to the result of
-               bzrlib.Branch.revision_history().
+               breezy.Branch.revision_history().
             3. Dictionnary mapping bzr bzr revision-ids to the database ids of
                the corresponding BranchRevision rows for this branch.
         """
@@ -1012,7 +1012,7 @@ class IBranchView(IHasOwner, IHasBranchTarget, IHasMergeProposals,
         You can only call this if a server returned by `get_ro_server` or
         `get_rw_server` is running.
 
-        :raise bzrlib.url_policy_open.BadUrl: If the branch is stacked
+        :raise breezy.url_policy_open.BadUrl: If the branch is stacked
             on or a reference to an unacceptable URL.
         """
 
diff --git a/lib/lp/code/interfaces/tests/test_branch.py b/lib/lp/code/interfaces/tests/test_branch.py
index af02ded..2eaab2f 100644
--- a/lib/lp/code/interfaces/tests/test_branch.py
+++ b/lib/lp/code/interfaces/tests/test_branch.py
@@ -5,9 +5,9 @@
 
 __metaclass__ = type
 
-from bzrlib.branch import format_registry as branch_format_registry
-from bzrlib.bzrdir import BzrProber
-from bzrlib.repository import format_registry as repo_format_registry
+from breezy.branch import format_registry as branch_format_registry
+from breezy.bzr import BzrProber
+from breezy.repository import format_registry as repo_format_registry
 
 from lp.code.bzr import (
     BranchFormat,
@@ -27,21 +27,21 @@ class TestFormatSupport(TestCase):
     """
 
     def test_control_format_complement(self):
-        self.bzrlib_is_subset(BzrProber.formats.keys(), ControlFormat)
+        self.breezy_is_subset(BzrProber.formats.keys(), ControlFormat)
 
     def test_branch_format_complement(self):
-        self.bzrlib_is_subset(branch_format_registry.keys(), BranchFormat)
+        self.breezy_is_subset(branch_format_registry.keys(), BranchFormat)
 
     def test_repository_format_complement(self):
-        self.bzrlib_is_subset(repo_format_registry.keys(), RepositoryFormat)
+        self.breezy_is_subset(repo_format_registry.keys(), RepositoryFormat)
 
-    def bzrlib_is_subset(self, bzrlib_formats, launchpad_enum):
-        """Ensure the bzr format marker list is a subset of launchpad."""
-        bzrlib_format_strings = set(bzrlib_formats)
+    def breezy_is_subset(self, breezy_formats, launchpad_enum):
+        """Ensure the Breezy format marker list is a subset of Launchpad."""
+        breezy_format_strings = set(breezy_formats)
         launchpad_format_strings = set(format.title for format
                                        in launchpad_enum.items)
         self.assertEqual(
-            set(), bzrlib_format_strings.difference(launchpad_format_strings))
+            set(), breezy_format_strings.difference(launchpad_format_strings))
 
     def test_repositoryDescriptions(self):
         self.checkDescriptions(RepositoryFormat)
diff --git a/lib/lp/code/mail/codereviewcomment.py b/lib/lp/code/mail/codereviewcomment.py
index 62706be..760d923 100644
--- a/lib/lp/code/mail/codereviewcomment.py
+++ b/lib/lp/code/mail/codereviewcomment.py
@@ -10,7 +10,7 @@ __all__ = [
     'CodeReviewCommentMailer',
     ]
 
-from bzrlib.patches import BinaryPatch
+from breezy.patches import BinaryPatch
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
@@ -174,9 +174,9 @@ def format_comment(comment):
     """Returns a list of correctly formatted comment(s)."""
     comment_lines = []
     if comment is not None:
-        comment_lines.append('')
+        comment_lines.append(b'')
         comment_lines.extend(comment.splitlines())
-        comment_lines.append('')
+        comment_lines.append(b'')
     return comment_lines
 
 
@@ -201,7 +201,7 @@ def build_inline_comments_section(comments, diff_text):
 
         if isinstance(patch, dict) and 'dirty_head' in patch:
             for line in patch['dirty_head']:
-                dirty_head.append(u'> %s' % line.rstrip('\n'))
+                dirty_head.append(b'> %s' % line.rstrip(b'\n'))
                 line_count += 1  # inc for dirty headers
                 comment = comments.get(str(line_count))
                 if comment:
@@ -213,7 +213,7 @@ def build_inline_comments_section(comments, diff_text):
         if type(patch) is BinaryPatch:
             if dirty_comment:
                 result_lines.extend(dirty_head)
-                result_lines.append(u'> %s' % str(patch).rstrip('\n'))
+                result_lines.append(b'> %s' % patch.as_bytes().rstrip(b'\n'))
             line_count += 1
             comment = comments.get(str(line_count))
             if comment:
@@ -224,7 +224,7 @@ def build_inline_comments_section(comments, diff_text):
             line_count += 1  # inc patch headers
             comment = comments.get(str(line_count))
 
-            patch_lines.append('> {0}'.format(ph))
+            patch_lines.append(b'> %s' % ph)
             if comment:
                 patch_lines.extend(format_comment(comment))
                 patch_comment = True
@@ -236,8 +236,7 @@ def build_inline_comments_section(comments, diff_text):
 
             # add context line (hunk header)
             line_count += 1  # inc hunk context line
-            hunk_lines.append(u'> %s' % hunk.get_header().rstrip('\n').decode(
-                'utf-8', 'replace'))
+            hunk_lines.append(b'> %s' % hunk.get_header().rstrip(b'\n'))
 
             # comment for context line (hunk header)
             comment = comments.get(str(line_count))
@@ -248,11 +247,9 @@ def build_inline_comments_section(comments, diff_text):
             for hunk_line in hunk.lines:
                 # A single HunkLine can actually represent multiple
                 # lines in the "No newline at end of file" case.
-                hunk_line = str(hunk_line)
-                for line in hunk_line.splitlines():
+                for line in hunk_line.as_bytes().splitlines():
                     line_count += 1  # inc hunk lines
-                    hunk_lines.append(u'> %s' % line.rstrip('\n').decode(
-                        'utf-8', 'replace'))
+                    hunk_lines.append(b'> %s' % line.rstrip(b'\n'))
                     comment = comments.get(str(line_count))
                     if comment:
                         hunk_lines.extend(format_comment(comment))
@@ -270,5 +267,5 @@ def build_inline_comments_section(comments, diff_text):
         elif dirty_comment:
             result_lines.extend(dirty_head)
 
-    result_text = '\n'.join(result_lines)
+    result_text = b'\n'.join(result_lines).decode('UTF-8', errors='replace')
     return '\n\nDiff comments:\n\n%s\n\n' % result_text
diff --git a/lib/lp/code/mail/patches.py b/lib/lp/code/mail/patches.py
index 5b5ccac..11e655d 100644
--- a/lib/lp/code/mail/patches.py
+++ b/lib/lp/code/mail/patches.py
@@ -1,4 +1,4 @@
-# This file was partially cloned from bzr-2.6.0-lp-3 (bzrlib.patches) and
+# This file was partially cloned from breezy 3.0.0 (breezy.patches) and
 # customised for LP.
 #
 # Copyright (C) 2005-2010 Aaron Bentley, Canonical Ltd
@@ -20,7 +20,7 @@
 
 from __future__ import absolute_import
 
-from bzrlib.patches import (
+from breezy.patches import (
     binary_files_re,
     hunk_from_header,
     parse_patch,
@@ -50,10 +50,10 @@ def iter_file_patch(iter_lines, allow_dirty=False, keep_dirty=False):
     beginning = True
     in_git_patch = False
 
-    dirty_headers = ('=== ', 'diff ', 'index ')
+    dirty_headers = (b'=== ', b'diff ', b'index ')
     for line in iter_lines:
         # preserve bzr modified/added headers and blank lines
-        if line.startswith(dirty_headers) or not line.strip('\n'):
+        if line.startswith(dirty_headers) or not line.strip(b'\n'):
             if len(saved_lines) > 0:
                 if keep_dirty and len(dirty_head) > 0:
                     yield {'saved_lines': saved_lines,
@@ -63,7 +63,7 @@ def iter_file_patch(iter_lines, allow_dirty=False, keep_dirty=False):
                     yield saved_lines
                 in_git_patch = False
                 saved_lines = []
-            if line.startswith('diff --git'):
+            if line.startswith(b'diff --git'):
                 in_git_patch = True
             dirty_head.append(line)
             continue
@@ -73,14 +73,14 @@ def iter_file_patch(iter_lines, allow_dirty=False, keep_dirty=False):
             # in the patch before the next "diff" header line can do so.
             dirty_head.append(line)
             continue
-        if line.startswith('*** '):
+        if line.startswith(b'*** '):
             continue
-        if line.startswith('#'):
+        if line.startswith(b'#'):
             continue
         elif orig_range > 0:
-            if line.startswith('-') or line.startswith(' '):
+            if line.startswith(b'-') or line.startswith(b' '):
                 orig_range -= 1
-        elif line.startswith('--- ') or regex.match(line):
+        elif line.startswith(b'--- ') or regex.match(line):
             if allow_dirty and beginning:
                 # Patches can have "junk" at the beginning
                 # Stripping junk from the end of patches is handled when we
@@ -95,7 +95,7 @@ def iter_file_patch(iter_lines, allow_dirty=False, keep_dirty=False):
                     yield saved_lines
                 in_git_patch = False
             saved_lines = []
-        elif line.startswith('@@'):
+        elif line.startswith(b'@@'):
             hunk = hunk_from_header(line)
             orig_range = hunk.orig_range
         saved_lines.append(line)
@@ -116,12 +116,11 @@ def parse_patches(iter_lines, allow_dirty=False, keep_dirty=False):
     :kwarg keep_dirty: If True, returns a dict of patches with dirty headers.
         Default False.
     '''
-    patches = []
     for patch_lines in iter_file_patch(iter_lines, allow_dirty, keep_dirty):
         if 'dirty_head' in patch_lines:
-            patches.append({'patch': parse_patch(
-                patch_lines['saved_lines'], allow_dirty),
-                'dirty_head': patch_lines['dirty_head']})
+            yield {
+                'patch': parse_patch(patch_lines['saved_lines'], allow_dirty),
+                'dirty_head': patch_lines['dirty_head'],
+                }
         else:
-            patches.append(parse_patch(patch_lines, allow_dirty))
-    return patches
+            yield parse_patch(patch_lines, allow_dirty)
diff --git a/lib/lp/code/model/branch.py b/lib/lp/code/model/branch.py
index 691b0c9..c95247a 100644
--- a/lib/lp/code/model/branch.py
+++ b/lib/lp/code/model/branch.py
@@ -14,9 +14,9 @@ import json
 import operator
 import os.path
 
-from bzrlib import urlutils
-from bzrlib.revision import NULL_REVISION
-from bzrlib.url_policy_open import open_only_scheme
+from breezy import urlutils
+from breezy.revision import NULL_REVISION
+from breezy.url_policy_open import open_only_scheme
 from lazr.lifecycle.event import ObjectCreatedEvent
 import pytz
 import six
diff --git a/lib/lp/code/model/branchjob.py b/lib/lp/code/model/branchjob.py
index 38a961f..8cf99c9 100644
--- a/lib/lp/code/model/branchjob.py
+++ b/lib/lp/code/model/branchjob.py
@@ -19,20 +19,20 @@ import shutil
 from StringIO import StringIO
 import tempfile
 
-from bzrlib.branch import Branch as BzrBranch
-from bzrlib.diff import show_diff_trees
-from bzrlib.errors import (
+from breezy.branch import Branch as BzrBranch
+from breezy.diff import show_diff_trees
+from breezy.errors import (
     NoSuchFile,
     NotBranchError,
     )
-from bzrlib.log import (
+from breezy.log import (
     log_formatter,
     show_log,
     )
-from bzrlib.revision import NULL_REVISION
-from bzrlib.revisionspec import RevisionInfo
-from bzrlib.transport import get_transport
-from bzrlib.upgrade import upgrade
+from breezy.revision import NULL_REVISION
+from breezy.revisionspec import RevisionInfo
+from breezy.transport import get_transport
+from breezy.upgrade import upgrade
 from lazr.delegates import delegate_to
 from lazr.enum import (
     DBEnumeratedType,
@@ -533,7 +533,7 @@ class RevisionsAddedJob(BranchJobDerived):
         repository = self.bzr_branch.repository
         added_revisions = repository.get_graph().find_unique_ancestors(
             self.last_revision_id, [self.last_scanned_id])
-        # Avoid hitting the database since bzrlib makes it easy to check.
+        # Avoid hitting the database since breezy makes it easy to check.
         # There are possibly more efficient ways to get the mainline
         # revisions, but this is simple and it works.
         history = branch_revision_history(self.bzr_branch)
@@ -625,7 +625,7 @@ class RevisionsAddedJob(BranchJobDerived):
         """Determine which revisions were merged by this revision.
 
         :param revision_id: ID of the revision to examine.
-        :param graph: a bzrlib.graph.Graph.
+        :param graph: a breezy.graph.Graph.
         :return: a set of revision IDs.
         """
         parents = graph.get_parent_map([revision_id])[revision_id]
@@ -901,7 +901,7 @@ class RosettaUploadJob(BranchJobDerived):
                             continue
                         file_id, (from_path, to_path) = changed_file[:2]
                         changed_files.append((
-                            to_path, to_tree.get_file_text(file_id)))
+                            to_path, to_tree.get_file_text(to_path)))
             finally:
                 from_tree.unlock()
         finally:
diff --git a/lib/lp/code/model/branchlookup.py b/lib/lp/code/model/branchlookup.py
index 18d8744..b0012e7 100644
--- a/lib/lp/code/model/branchlookup.py
+++ b/lib/lp/code/model/branchlookup.py
@@ -9,7 +9,7 @@ __metaclass__ = type
 __all__ = []
 
 
-from bzrlib.urlutils import escape
+from breezy.urlutils import escape
 from lazr.enum import DBItem
 from lazr.uri import (
     InvalidURIError,
diff --git a/lib/lp/code/model/diff.py b/lib/lp/code/model/diff.py
index ac8d525..500dd5c 100644
--- a/lib/lp/code/model/diff.py
+++ b/lib/lp/code/model/diff.py
@@ -16,14 +16,14 @@ from operator import attrgetter
 import sys
 from uuid import uuid1
 
-from bzrlib import trace
-from bzrlib.diff import show_diff_trees
-from bzrlib.merge import Merge3Merger
-from bzrlib.patches import (
+from breezy import trace
+from breezy.diff import show_diff_trees
+from breezy.merge import Merge3Merger
+from breezy.patches import (
     parse_patches,
     Patch,
     )
-from bzrlib.plugins.difftacular.generate_diff import diff_ignore_branches
+from breezy.plugins.difftacular.generate_diff import diff_ignore_branches
 from lazr.delegates import delegate_to
 import simplejson
 from sqlobject import (
diff --git a/lib/lp/code/model/directbranchcommit.py b/lib/lp/code/model/directbranchcommit.py
index 4dd4d46..0b7a902 100644
--- a/lib/lp/code/model/directbranchcommit.py
+++ b/lib/lp/code/model/directbranchcommit.py
@@ -12,9 +12,9 @@ __all__ = [
 
 import os.path
 
-from bzrlib.generate_ids import gen_file_id
-from bzrlib.revision import NULL_REVISION
-from bzrlib.transform import (
+from breezy.bzr.generate_ids import gen_file_id
+from breezy.revision import NULL_REVISION
+from breezy.transform import (
     ROOT_PARENT,
     TransformPreview,
     )
@@ -226,10 +226,11 @@ class DirectBranchCommit:
             if rev_id == NULL_REVISION:
                 if list(self.transform_preview.iter_changes()) == []:
                     return
+            self.transform_preview.fixup_new_roots()
             committer_id = self.getBzrCommitterID()
             # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
             # required to generate the revision-id.
-            with override_environ(BZR_EMAIL=committer_id):
+            with override_environ(BRZ_EMAIL=committer_id):
                 new_rev_id = self.transform_preview.commit(
                     self.bzrbranch, commit_message, self.merge_parents,
                     committer=committer_id)
diff --git a/lib/lp/code/model/gitrepository.py b/lib/lp/code/model/gitrepository.py
index 5d4607a..eadc8da 100644
--- a/lib/lp/code/model/gitrepository.py
+++ b/lib/lp/code/model/gitrepository.py
@@ -27,7 +27,7 @@ from itertools import (
 from operator import attrgetter
 from urllib import quote_plus
 
-from bzrlib import urlutils
+from breezy import urlutils
 from lazr.enum import DBItem
 from lazr.lifecycle.event import ObjectModifiedEvent
 from lazr.lifecycle.snapshot import Snapshot
diff --git a/lib/lp/code/model/revision.py b/lib/lp/code/model/revision.py
index 119ac41..4895ebb 100644
--- a/lib/lp/code/model/revision.py
+++ b/lib/lp/code/model/revision.py
@@ -16,7 +16,7 @@ from datetime import (
     )
 import email
 
-from bzrlib.revision import NULL_REVISION
+from breezy.revision import NULL_REVISION
 import pytz
 from sqlobject import (
     BoolCol,
@@ -322,7 +322,7 @@ class RevisionSet:
         This works around a bug in Python that causes datetime.fromtimestamp
         to raise an exception if it is given a negative, fractional timestamp.
 
-        :param timestamp: A timestamp from a bzrlib.revision.Revision
+        :param timestamp: A timestamp from a breezy.revision.Revision
         :type timestamp: float
 
         :return: A datetime corresponding to the given timestamp.
diff --git a/lib/lp/code/model/sourcepackagerecipedata.py b/lib/lp/code/model/sourcepackagerecipedata.py
index a30b3c2..e0801bf 100644
--- a/lib/lp/code/model/sourcepackagerecipedata.py
+++ b/lib/lp/code/model/sourcepackagerecipedata.py
@@ -13,7 +13,7 @@ __all__ = ['SourcePackageRecipeData']
 
 import re
 
-from bzrlib.plugins.builder.recipe import (
+from breezy.plugins.builder.recipe import (
     BaseRecipeBranch,
     MergeInstruction,
     NestInstruction,
diff --git a/lib/lp/code/model/tests/test_branch.py b/lib/lp/code/model/tests/test_branch.py
index ecad508..2bd0b62 100644
--- a/lib/lp/code/model/tests/test_branch.py
+++ b/lib/lp/code/model/tests/test_branch.py
@@ -13,10 +13,10 @@ from datetime import (
     )
 import json
 
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDir
-from bzrlib.revision import NULL_REVISION
-from bzrlib.url_policy_open import BadUrl
+from breezy.branch import Branch
+from breezy.bzr.bzrdir import BzrDir
+from breezy.revision import NULL_REVISION
+from breezy.url_policy_open import BadUrl
 from pytz import UTC
 from sqlobject import SQLObjectNotFound
 from storm.exceptions import LostObjectError
@@ -2257,7 +2257,7 @@ class TestRevisionHistory(TestCaseWithFactory):
     def test_tip_revision_when_no_revisions(self):
         # When a branch has no revisions but does have Bazaar data, its tip
         # revision is None and its last_scanned_id is
-        # bzrlib.revision.NULL_REVISION.
+        # breezy.revision.NULL_REVISION.
         branch = self.factory.makeBranch()
         branch.updateScannedDetails(None, 0)
         self.assertEqual(NULL_REVISION, branch.last_scanned_id)
@@ -3276,7 +3276,7 @@ class TestGetBzrBranch(TestCaseWithFactory):
         db_branch, tree = self.create_branch_and_tree()
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             revid = tree.commit('')
         bzr_branch = db_branch.getBzrBranch()
         self.assertEqual(revid, bzr_branch.last_revision())
diff --git a/lib/lp/code/model/tests/test_branchjob.py b/lib/lp/code/model/tests/test_branchjob.py
index 66badbf..0c4a893 100644
--- a/lib/lp/code/model/tests/test_branchjob.py
+++ b/lib/lp/code/model/tests/test_branchjob.py
@@ -11,11 +11,11 @@ import datetime
 import os
 import shutil
 
-from bzrlib import errors as bzr_errors
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDir
-from bzrlib.revision import NULL_REVISION
-from bzrlib.transport import get_transport
+from breezy import errors as bzr_errors
+from breezy.branch import Branch
+from breezy.bzr.bzrdir import BzrDir
+from breezy.revision import NULL_REVISION
+from breezy.transport import get_transport
 from fixtures import MockPatch
 import pytz
 from sqlobject import SQLObjectNotFound
@@ -149,7 +149,7 @@ class TestBranchScanJob(TestCaseWithFactory):
         db_branch, bzr_tree = self.create_branch_and_tree()
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             bzr_tree.commit('First commit', rev_id=b'rev1')
             bzr_tree.commit('Second commit', rev_id=b'rev2')
             bzr_tree.commit('Third commit', rev_id=b'rev3')
@@ -177,7 +177,7 @@ class TestBranchScanJob(TestCaseWithFactory):
         db_branch, bzr_tree = self.create_branch_and_tree()
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             bzr_tree.commit('First commit', rev_id=b'rev1')
             LaunchpadZopelessLayer.commit()
 
@@ -198,7 +198,7 @@ class TestBranchScanJob(TestCaseWithFactory):
         private_bug = self.factory.makeBug(
             target=product, information_type=InformationType.USERDATA)
         bug_line = b'https://launchpad.net/bugs/%s fixed' % private_bug.id
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             bzr_tree.commit(
                 'First commit', rev_id=b'rev1', revprops={b'bugs': bug_line})
         job = BranchScanJob.create(db_branch)
@@ -314,7 +314,7 @@ class TestBranchUpgradeJob(TestCaseWithFactory):
         db_branch, tree = self.create_branch_and_tree()
         branch2 = BzrDir.create_branch_convenience('.')
         tree.branch.set_stacked_on_url(branch2.base)
-        branch2.bzrdir.destroy_branch()
+        branch2.controldir.destroy_branch()
         # Create BranchUpgradeJob manually, because we're trying to upgrade a
         # branch that doesn't need upgrading.
         requester = self.factory.makePerson()
@@ -463,7 +463,7 @@ class TestRevisionsAddedJob(TestCaseWithFactory):
         try:
             # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
             # required to generate the revision-id.
-            with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+            with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
                 tree.commit('rev1', rev_id=b'rev1')
                 tree.commit('rev2', rev_id=b'rev2')
                 tree.commit('rev3', rev_id=b'rev3')
@@ -492,7 +492,7 @@ class TestRevisionsAddedJob(TestCaseWithFactory):
         tree.add_parent_tree_id(b'rev3')
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit('rev3a', rev_id=b'rev3a')
         self.updateDBRevisions(branch, tree.branch, [b'rev3', b'rev3a'])
         job = RevisionsAddedJob.create(branch, 'rev1', 'rev3', '')
@@ -533,7 +533,7 @@ class TestRevisionsAddedJob(TestCaseWithFactory):
         self.addCleanup(tree.unlock)
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit(
                 'rev1', rev_id=b'rev1', timestamp=1000, timezone=0,
                 committer='J. Random Hacker <jrandom@xxxxxxxxxxx>')
@@ -552,14 +552,14 @@ class TestRevisionsAddedJob(TestCaseWithFactory):
         tree.branch.nick = 'nicholas'
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit('rev1')
-            tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
+            tree2 = tree.controldir.sprout('tree2').open_workingtree()
             tree2.commit('rev2a', rev_id=b'rev2a-id', committer='foo@')
             tree2.commit('rev3', rev_id=b'rev3-id',
                          authors=['bar@', 'baz@xxxxxxxxxx'])
             tree.merge_from_branch(tree2.branch)
-            tree3 = tree.bzrdir.sprout('tree3').open_workingtree()
+            tree3 = tree.controldir.sprout('tree3').open_workingtree()
             tree3.commit('rev2b', rev_id=b'rev2b-id', committer='qux@')
             tree.merge_from_branch(tree3.branch, force=True)
             if include_ghost:
@@ -808,17 +808,17 @@ class TestRevisionsAddedJob(TestCaseWithFactory):
         self.useBzrBranches(direct_database=True)
         db_branch, tree = self.create_branch_and_tree()
         first_revision = b'rev-1'
-        tree.bzrdir.root_transport.put_bytes('hello.txt', 'Hello World\n')
+        tree.controldir.root_transport.put_bytes('hello.txt', b'Hello World\n')
         tree.add('hello.txt')
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit(
                 rev_id=first_revision, message="Log message",
                 committer="Joe Bloggs <joe@xxxxxxxxxxx>",
                 timestamp=1000000000.0, timezone=0)
-            tree.bzrdir.root_transport.put_bytes(
-                'hello.txt', 'Hello World\n\nFoo Bar\n')
+            tree.controldir.root_transport.put_bytes(
+                'hello.txt', b'Hello World\n\nFoo Bar\n')
             second_revision = b'rev-2'
             tree.commit(
                 rev_id=second_revision, message="Extended contents",
@@ -864,7 +864,7 @@ class TestRevisionsAddedJob(TestCaseWithFactory):
         rev_id = b'rev-1'
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit(
                 rev_id=rev_id, message="Non ASCII: \xe9",
                 committer="Non ASCII: \xed", timestamp=1000000000.0,
@@ -971,8 +971,9 @@ class TestRosettaUploadJob(TestCaseWithFactory):
             except IndexError:
                 file_content = self.factory.getUniqueString()
             dname = os.path.dirname(file_name)
-            self.tree.bzrdir.root_transport.clone(dname).create_prefix()
-            self.tree.bzrdir.root_transport.put_bytes(file_name, file_content)
+            self.tree.controldir.root_transport.clone(dname).create_prefix()
+            self.tree.controldir.root_transport.put_bytes(
+                file_name, file_content)
         if len(files) > 0:
             self.tree.smart_add(
                 [self.tree.abspath(file_pair[0]) for file_pair in files])
@@ -980,7 +981,7 @@ class TestRosettaUploadJob(TestCaseWithFactory):
             commit_message = self.factory.getUniqueString('commit')
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             revision_id = self.tree.commit(commit_message)
         self.branch.last_scanned_id = revision_id
         self.branch.last_mirrored_id = revision_id
@@ -1076,7 +1077,7 @@ class TestRosettaUploadJob(TestCaseWithFactory):
         # An empty POT cannot be uploaded, if if the product series is
         # configured for template import.
         entries = self._runJobWithFile(
-            TranslationsBranchImportMode.IMPORT_TEMPLATES, 'empty.pot', '')
+            TranslationsBranchImportMode.IMPORT_TEMPLATES, 'empty.pot', b'')
         self.assertEqual(entries, [])
 
     def test_upload_hidden_pot(self):
@@ -1103,7 +1104,7 @@ class TestRosettaUploadJob(TestCaseWithFactory):
     def test_upload_pot_content(self):
         # The content of the uploaded file is stored in the librarian.
         # The uploader of a POT is the series owner.
-        POT_CONTENT = "pot content\n"
+        POT_CONTENT = b"pot content\n"
         self._runJobWithFile(
             TranslationsBranchImportMode.IMPORT_TEMPLATES,
             'foo.pot', POT_CONTENT)
diff --git a/lib/lp/code/model/tests/test_branchmergeproposaljobs.py b/lib/lp/code/model/tests/test_branchmergeproposaljobs.py
index 8f1fcca..9836caf 100644
--- a/lib/lp/code/model/tests/test_branchmergeproposaljobs.py
+++ b/lib/lp/code/model/tests/test_branchmergeproposaljobs.py
@@ -190,7 +190,7 @@ class TestMergeProposalNeedsReviewEmailJobBzr(
         target_branch, tree = self.create_branch_and_tree()
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit('test')
         source_branch = self.factory.makeProductBranch(
             product=target_branch.product)
@@ -212,7 +212,7 @@ class TestMergeProposalNeedsReviewEmailJobBzr(
         tree = self.create_branch_and_tree(db_branch=bmp.target_branch)[1]
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit('Initial commit')
         self.createBzrBranch(bmp.source_branch, tree.branch)
         self.factory.makeRevisionsForBranch(bmp.source_branch, count=1)
diff --git a/lib/lp/code/model/tests/test_diff.py b/lib/lp/code/model/tests/test_diff.py
index f082a8e..f4ec2ce 100644
--- a/lib/lp/code/model/tests/test_diff.py
+++ b/lib/lp/code/model/tests/test_diff.py
@@ -12,8 +12,8 @@ from difflib import unified_diff
 import logging
 from textwrap import dedent
 
-from bzrlib import trace
-from bzrlib.patches import (
+from breezy import trace
+from breezy.patches import (
     InsertLine,
     parse_patches,
     RemoveLine,
@@ -565,7 +565,7 @@ class TestPreviewDiff(DiffTestCase):
         reload(trace)
         bmp, source_rev_id, target_rev_id = self.createExampleBzrMerge()
         handler = RecordLister()
-        logger = logging.getLogger('bzr')
+        logger = logging.getLogger('brz')
         logger.addHandler(handler)
         try:
             PreviewDiff.fromBranchMergeProposal(bmp)
diff --git a/lib/lp/code/model/tests/test_gitref.py b/lib/lp/code/model/tests/test_gitref.py
index 2152b03..9b546fe 100644
--- a/lib/lp/code/model/tests/test_gitref.py
+++ b/lib/lp/code/model/tests/test_gitref.py
@@ -14,7 +14,7 @@ from datetime import (
 import hashlib
 import json
 
-from bzrlib import urlutils
+from breezy import urlutils
 import pytz
 import responses
 from storm.store import Store
diff --git a/lib/lp/code/model/tests/test_gitrepository.py b/lib/lp/code/model/tests/test_gitrepository.py
index e679142..a3b8e81 100644
--- a/lib/lp/code/model/tests/test_gitrepository.py
+++ b/lib/lp/code/model/tests/test_gitrepository.py
@@ -16,7 +16,7 @@ from functools import partial
 import hashlib
 import json
 
-from bzrlib import urlutils
+from breezy import urlutils
 from fixtures import MockPatch
 from lazr.lifecycle.event import ObjectModifiedEvent
 from pymacaroons import Macaroon
diff --git a/lib/lp/code/model/tests/test_sourcepackagerecipe.py b/lib/lp/code/model/tests/test_sourcepackagerecipe.py
index aa950f2..fd47336 100644
--- a/lib/lp/code/model/tests/test_sourcepackagerecipe.py
+++ b/lib/lp/code/model/tests/test_sourcepackagerecipe.py
@@ -13,7 +13,7 @@ from datetime import (
     )
 import textwrap
 
-from bzrlib.plugins.builder.recipe import ForbiddenInstructionError
+from breezy.plugins.builder.recipe import ForbiddenInstructionError
 from pytz import UTC
 from storm.locals import Store
 from testtools.matchers import Equals
diff --git a/lib/lp/code/scripts/tests/test_scan_branches.py b/lib/lp/code/scripts/tests/test_scan_branches.py
index ddaeea8..4f5783f 100644
--- a/lib/lp/code/scripts/tests/test_scan_branches.py
+++ b/lib/lp/code/scripts/tests/test_scan_branches.py
@@ -39,7 +39,7 @@ class TestScanBranches(TestCaseWithFactory):
         target, target_tree = self.create_branch_and_tree(db_branch=db_branch)
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             target_tree.commit('First commit', rev_id='rev1')
             target_tree.commit('Second commit', rev_id='rev2')
             target_tree.commit('Third commit', rev_id='rev3')
diff --git a/lib/lp/code/scripts/tests/test_sendbranchmail.py b/lib/lp/code/scripts/tests/test_sendbranchmail.py
index bee4c9f..e7e983d 100644
--- a/lib/lp/code/scripts/tests/test_sendbranchmail.py
+++ b/lib/lp/code/scripts/tests/test_sendbranchmail.py
@@ -32,12 +32,12 @@ class TestSendbranchmail(TestCaseWithFactory):
             BranchSubscriptionDiffSize.WHOLEDIFF,
             CodeReviewNotificationLevel.FULL,
             branch.registrant)
-        transport = tree.bzrdir.root_transport
-        transport.put_bytes('foo', 'bar')
+        transport = tree.controldir.root_transport
+        transport.put_bytes('foo', b'bar')
         tree.add('foo')
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit('Added foo.', rev_id='rev1')
         return branch, tree
 
@@ -65,10 +65,10 @@ class TestSendbranchmail(TestCaseWithFactory):
         """RevisionsAddedJobs are run by sendbranchmail."""
         self.useBzrBranches()
         branch, tree = self.createBranch()
-        tree.bzrdir.root_transport.put_bytes('foo', 'baz')
+        tree.controldir.root_transport.put_bytes('foo', b'baz')
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             tree.commit('Added foo.', rev_id='rev2')
         job = RevisionsAddedJob.create(
             branch, 'rev1', 'rev2', 'from@xxxxxxxxxxx')
diff --git a/lib/lp/code/scripts/tests/test_upgrade_branches.py b/lib/lp/code/scripts/tests/test_upgrade_branches.py
index a349d90..b95dc8b 100644
--- a/lib/lp/code/scripts/tests/test_upgrade_branches.py
+++ b/lib/lp/code/scripts/tests/test_upgrade_branches.py
@@ -4,7 +4,7 @@
 """Test the upgrade_branches script."""
 
 
-from bzrlib.branch import Branch as BzrBranch
+from breezy.branch import Branch as BzrBranch
 import transaction
 
 from lp.code.model.branch import (
diff --git a/lib/lp/code/stories/branches/xx-bazaar-home.txt b/lib/lp/code/stories/branches/xx-bazaar-home.txt
index ec8c20e..5b90cca 100644
--- a/lib/lp/code/stories/branches/xx-bazaar-home.txt
+++ b/lib/lp/code/stories/branches/xx-bazaar-home.txt
@@ -1,15 +1,15 @@
 The Launchpad Code front page
 =============================
 
-First we manually set the Bazaar version, so that this document will not need
-updating when Launchpad upgrades Bazaar.
+First we manually set the Breezy version, so that this document will not need
+updating when Launchpad upgrades Breezy.
 
-    >>> import bzrlib
-    >>> bzrlib_version = bzrlib.__version__
-    >>> bzrlib.__version__ = '0.92.0'
+    >>> import breezy
+    >>> breezy_version = breezy.__version__
+    >>> breezy.__version__ = '3.0.0'
 
 
-Check that the Bazaar home page works.
+Check that the Code home page works.
 
     >>> browser.open('http://code.launchpad.test/')
     >>> footer = find_tag_by_id(browser.contents, 'application-footer')
@@ -18,12 +18,12 @@ Check that the Bazaar home page works.
     30 branches registered in
     6 projects
     1 imported branches
-    Launchpad uses Bazaar 0.92.0.
+    Launchpad uses Breezy 3.0.0.
 
 
-Restore the original Bazaar version:
+Restore the original Breezy version:
 
-    >>> bzrlib.__version__ = bzrlib_version
+    >>> breezy.__version__ = breezy_version
 
 
 The main code home page now has a subset of the project tag cloud,
diff --git a/lib/lp/code/stories/webservice/xx-branch.txt b/lib/lp/code/stories/webservice/xx-branch.txt
index f198608..18c3ea0 100644
--- a/lib/lp/code/stories/webservice/xx-branch.txt
+++ b/lib/lp/code/stories/webservice/xx-branch.txt
@@ -3,7 +3,7 @@ Introduction
 
 Launchpad provides two ways to programmatically interact with your
 branches. You can either interact with the branches themselves using
-`bzrlib`, or you can use Launchpad's webservice APIs to explore
+`breezy`, or you can use Launchpad's webservice APIs to explore
 information about the branches and how they relate to the rest of
 the things on Launchpad.
 
diff --git a/lib/lp/code/templates/bazaar-index.pt b/lib/lp/code/templates/bazaar-index.pt
index cdd9bcd..b3ae707 100644
--- a/lib/lp/code/templates/bazaar-index.pt
+++ b/lib/lp/code/templates/bazaar-index.pt
@@ -128,8 +128,8 @@
           </a>
         </div>
         <div>
-          Launchpad uses <a href="http://bazaar.canonical.com/";>Bazaar</a>
-          <tal:version tal:content="view/bzr_version">2.0</tal:version>.
+          Launchpad uses <a href="https://www.breezy-vcs.org/";>Breezy</a>
+          <tal:version tal:content="view/brz_version">3.0.0</tal:version>.
         </div>
       </div>
 
diff --git a/lib/lp/code/tests/helpers.py b/lib/lp/code/tests/helpers.py
index 1b9f7d7..2955528 100644
--- a/lib/lp/code/tests/helpers.py
+++ b/lib/lp/code/tests/helpers.py
@@ -26,7 +26,7 @@ from datetime import timedelta
 from difflib import unified_diff
 from itertools import count
 
-from bzrlib.plugins.builder.recipe import RecipeParser
+from breezy.plugins.builder.recipe import RecipeParser
 import fixtures
 import transaction
 from zope.component import getUtility
diff --git a/lib/lp/code/tests/test_bzr.py b/lib/lp/code/tests/test_bzr.py
index 37afc6c..6a62463 100644
--- a/lib/lp/code/tests/test_bzr.py
+++ b/lib/lp/code/tests/test_bzr.py
@@ -7,12 +7,13 @@ from __future__ import absolute_import, print_function, unicode_literals
 
 __metaclass__ = type
 
-from bzrlib.errors import NoSuchRevision
-from bzrlib.revision import NULL_REVISION
-from bzrlib.tests import (
+from breezy.errors import NoSuchRevision
+from breezy.revision import NULL_REVISION
+from breezy.tests import (
     TestCaseInTempDir,
     TestCaseWithTransport,
     )
+import six
 
 from lp.code.bzr import (
     branch_revision_history,
@@ -49,7 +50,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_2a(self):
         # Test the 2a branch format.
-        branch = self.make_branch('test', '2a')
+        branch = self.make_branch('test', six.ensure_str('2a'))
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_7, formats[1])
@@ -57,7 +58,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_1_9(self):
         # Test the 1.9 branch format.
-        branch = self.make_branch('test', '1.9')
+        branch = self.make_branch('test', six.ensure_str('1.9'))
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_7, formats[1])
@@ -65,7 +66,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_packs(self):
         # Test the packs branch format.
-        branch = self.make_branch('test', 'pack-0.92')
+        branch = self.make_branch('test', six.ensure_str('pack-0.92'))
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_6, formats[1])
@@ -73,7 +74,7 @@ class TestGetBranchFormats(TestCaseInTempDir):
 
     def test_get_branch_format_knits(self):
         # Test the knits branch format.
-        branch = self.make_branch('test', 'knit')
+        branch = self.make_branch('test', six.ensure_str('knit'))
         formats = get_branch_formats(branch)
         self.assertEqual(ControlFormat.BZR_METADIR_1, formats[0])
         self.assertEqual(BranchFormat.BZR_BRANCH_5, formats[1])
@@ -89,7 +90,7 @@ class TestBranchRevisionHistory(TestCaseWithTransport):
 
     def test_some_commits(self):
         branch = self.make_branch('test')
-        tree = branch.bzrdir.create_workingtree()
+        tree = branch.controldir.create_workingtree()
         tree.commit('acommit', rev_id=b'A')
         tree.commit('bcommit', rev_id=b'B')
         tree.commit('ccommit', rev_id=b'C')
@@ -109,7 +110,7 @@ class TestGetAncestry(TestCaseWithTransport):
     def test_some(self):
         # Verify ancestors are included.
         branch = self.make_branch('test')
-        tree = branch.bzrdir.create_workingtree()
+        tree = branch.controldir.create_workingtree()
         tree.commit('msg a', rev_id=b'A')
         tree.commit('msg b', rev_id=b'B')
         tree.commit('msg c', rev_id=b'C')
@@ -123,7 +124,7 @@ class TestGetAncestry(TestCaseWithTransport):
     def test_children(self):
         # Verify non-mainline children are included.
         branch = self.make_branch('test')
-        tree = branch.bzrdir.create_workingtree()
+        tree = branch.controldir.create_workingtree()
         tree.commit('msg a', rev_id=b'A')
         branch.generate_revision_history(NULL_REVISION)
         tree.set_parent_ids([])
diff --git a/lib/lp/code/xmlrpc/branch.py b/lib/lp/code/xmlrpc/branch.py
index ed0ce23..bd45c11 100644
--- a/lib/lp/code/xmlrpc/branch.py
+++ b/lib/lp/code/xmlrpc/branch.py
@@ -12,7 +12,7 @@ __all__ = [
 
 from xmlrpclib import Fault
 
-from bzrlib import urlutils
+from breezy import urlutils
 from zope.component import getUtility
 from zope.interface import (
     implementer,
diff --git a/lib/lp/code/xmlrpc/codehosting.py b/lib/lp/code/xmlrpc/codehosting.py
index 107b1e6..3c09e78 100644
--- a/lib/lp/code/xmlrpc/codehosting.py
+++ b/lib/lp/code/xmlrpc/codehosting.py
@@ -13,7 +13,7 @@ __all__ = [
 
 import datetime
 
-from bzrlib.urlutils import (
+from breezy.urlutils import (
     escape,
     unescape,
     )
diff --git a/lib/lp/code/xmlrpc/tests/test_branch.py b/lib/lp/code/xmlrpc/tests/test_branch.py
index 5b75b28..d035177 100644
--- a/lib/lp/code/xmlrpc/tests/test_branch.py
+++ b/lib/lp/code/xmlrpc/tests/test_branch.py
@@ -8,7 +8,7 @@ __metaclass__ = type
 import os
 import xmlrpclib
 
-from bzrlib import urlutils
+from breezy import urlutils
 from lazr.uri import URI
 from zope.security.proxy import removeSecurityProxy
 
diff --git a/lib/lp/code/xmlrpc/tests/test_codehosting.py b/lib/lp/code/xmlrpc/tests/test_codehosting.py
index 2491adc..c5ec059 100644
--- a/lib/lp/code/xmlrpc/tests/test_codehosting.py
+++ b/lib/lp/code/xmlrpc/tests/test_codehosting.py
@@ -8,8 +8,8 @@ __metaclass__ = type
 import datetime
 import os
 
-from bzrlib import bzrdir
-from bzrlib.urlutils import escape
+from breezy import controldir
+from breezy.urlutils import escape
 import pytz
 from testscenarios import (
     load_tests_apply_scenarios,
@@ -659,7 +659,7 @@ class CodehostingTest(WithScenarios, TestCaseWithFactory):
             branch, 'next_mirror_time', UTC_NOW)
 
     def getFormatStringsForFormatName(self, format_name):
-        default_format = bzrdir.format_registry.get(format_name)()
+        default_format = controldir.format_registry.get(format_name)()
         control_string = default_format.get_format_string()
         branch_string = default_format.get_branch_format().get_format_string()
         repository_string = \
diff --git a/lib/lp/codehosting/__init__.py b/lib/lp/codehosting/__init__.py
index 261a3aa..bd097f9 100644
--- a/lib/lp/codehosting/__init__.py
+++ b/lib/lp/codehosting/__init__.py
@@ -9,16 +9,21 @@ all plugins in the bzrplugins/ directory underneath the rocketfuel checkout.
 
 __metaclass__ = type
 __all__ = [
-    'get_bzr_path',
+    'get_brz_path',
     'get_BZR_PLUGIN_PATH_for_subprocess',
     ]
 
 
 import os
 
-import bzrlib
-from bzrlib.branch import Branch
-from bzrlib.plugin import load_plugins
+import breezy
+from breezy import ui as brz_ui
+from breezy.branch import Branch
+from breezy.library_state import BzrLibraryState as BrzLibraryState
+from breezy.plugin import load_plugins as brz_load_plugins
+# This import is needed so that brz's logger gets registered.
+import breezy.trace
+from bzrlib.plugin import load_plugins as bzr_load_plugins
 # This import is needed so that bzr's logger gets registered.
 import bzrlib.trace
 from zope.security import checker
@@ -26,9 +31,9 @@ from zope.security import checker
 from lp.services.config import config
 
 
-def get_bzr_path():
-    """Find the path to the copy of Bazaar for this rocketfuel instance"""
-    return os.path.join(config.root, 'bin', 'bzr')
+def get_brz_path():
+    """Find the path to the copy of Breezy for this rocketfuel instance"""
+    return os.path.join(config.root, 'bin', 'brz')
 
 
 def _get_bzr_plugins_path():
@@ -48,23 +53,50 @@ def get_BZR_PLUGIN_PATH_for_subprocess():
     return ":".join((_get_bzr_plugins_path(), "-site"))
 
 
-os.environ['BZR_PLUGIN_PATH'] = get_BZR_PLUGIN_PATH_for_subprocess()
+def _get_brz_plugins_path():
+    """Find the path to the Breezy plugins for this rocketfuel instance."""
+    return os.path.join(config.root, 'brzplugins')
 
-# We want to have full access to Launchpad's Bazaar plugins throughout the
-# codehosting package.
-load_plugins([_get_bzr_plugins_path()])
 
+def get_BRZ_PLUGIN_PATH_for_subprocess():
+    """Calculate the appropriate value for the BRZ_PLUGIN_PATH environment.
+
+    The '-site' token tells breezy not to include the 'site specific plugins
+    directory' (which is usually something like
+    /usr/lib/pythonX.Y/dist-packages/breezy/plugins/) in the plugin search
+    path, which would be inappropriate for Launchpad, which may have an
+    incompatible version of breezy in its virtualenv.
+    """
+    return ":".join((_get_brz_plugins_path(), "-site"))
 
-def load_bundled_plugin(plugin_name):
-    """Load a plugin bundled with Bazaar."""
-    from bzrlib.plugin import get_core_plugin_path
-    from bzrlib import plugins
-    if get_core_plugin_path() not in plugins.__path__:
-        plugins.__path__.append(get_core_plugin_path())
-    __import__("bzrlib.plugins.%s" % plugin_name)
 
+# We must explicitly initialize Breezy, as otherwise it will initialize
+# itself with a terminal-oriented UI.
+if breezy._global_state is None:
+    brz_state = BrzLibraryState(
+        ui=brz_ui.SilentUIFactory(), trace=breezy.trace.Config())
+    brz_state._start()
 
-load_bundled_plugin("weave_fmt")
+
+# XXX cjwatson 2019-06-13: Remove BZR_PLUGIN_PATH and supporting code once
+# all of Launchpad has been ported to Breezy.
+os.environ['BZR_PLUGIN_PATH'] = get_BZR_PLUGIN_PATH_for_subprocess()
+os.environ['BRZ_PLUGIN_PATH'] = get_BRZ_PLUGIN_PATH_for_subprocess()
+
+# Disable some Breezy plugins that are likely to cause trouble if used on
+# the server.  (Unfortunately there doesn't seem to be a good way to load
+# only explicitly-specified plugins at the moment.)
+os.environ['BRZ_DISABLE_PLUGINS'] = ':'.join([
+    'cvs',
+    'darcs',
+    'email',
+    'mtn',
+    ])
+
+# We want to have full access to Launchpad's Bazaar plugins throughout the
+# codehosting package.
+bzr_load_plugins([_get_bzr_plugins_path()])
+brz_load_plugins()
 
 
 def dont_wrap_class_and_subclasses(cls):
@@ -75,6 +107,6 @@ def dont_wrap_class_and_subclasses(cls):
 
 # Don't wrap Branch or its subclasses in Zope security proxies.  Make sure
 # the various LoomBranch classes are present first.
-import bzrlib.plugins.loom.branch
-bzrlib.plugins.loom.branch
+import breezy.plugins.loom.branch
+breezy.plugins.loom.branch
 dont_wrap_class_and_subclasses(Branch)
diff --git a/lib/lp/codehosting/bzrutils.py b/lib/lp/codehosting/bzrutils.py
index 52dcd7b..bd1dc4b 100644
--- a/lib/lp/codehosting/bzrutils.py
+++ b/lib/lp/codehosting/bzrutils.py
@@ -1,10 +1,10 @@
 # Copyright 2009 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""Utilities for dealing with Bazaar.
+"""Utilities for dealing with Breezy.
 
 Much of the code in here should be submitted upstream. The rest is code that
-integrates between Bazaar's infrastructure and Launchpad's infrastructure.
+integrates between Breezy's infrastructure and Launchpad's infrastructure.
 """
 
 __metaclass__ = type
@@ -28,30 +28,30 @@ from contextlib import contextmanager
 import os
 import sys
 
-from bzrlib import (
+from breezy import (
     config,
     trace,
     )
-from bzrlib.errors import (
+from breezy.branch import UnstackableBranchFormat
+from breezy.bzr.remote import (
+    RemoteBranch,
+    RemoteBzrDir,
+    RemoteRepository,
+    )
+from breezy.errors import (
     AppendRevisionsOnlyViolation,
     ConnectionTimeout,
     GhostRevisionsHaveNoRevno,
     NotStacked,
-    UnstackableBranchFormat,
     UnstackableRepositoryFormat,
     UnsupportedProtocol,
     )
-from bzrlib.remote import (
-    RemoteBranch,
-    RemoteBzrDir,
-    RemoteRepository,
-    )
-from bzrlib.transport import (
+from breezy.transport import (
     get_transport,
     register_transport,
     unregister_transport,
     )
-from bzrlib.transport.local import LocalTransport
+from breezy.transport.local import LocalTransport
 from lazr.uri import URI
 
 from lp.services.webapp.errorlog import (
@@ -221,7 +221,7 @@ class HttpAsLocalTransport(LocalTransport):
     """A LocalTransport that works using http URLs.
 
     We have this because the Launchpad database has constraints on URLs for
-    branches, disallowing file:/// URLs. bzrlib itself disallows
+    branches, disallowing file:/// URLs. breezy itself disallows
     file://localhost/ URLs.
     """
 
@@ -287,7 +287,7 @@ def get_vfs_format_classes(branch):
     if isinstance(repository, RemoteRepository):
         repository._ensure_real()
         repository = repository._real_repository
-    bzrdir = branch.bzrdir
+    bzrdir = branch.controldir
     if isinstance(bzrdir, RemoteBzrDir):
         bzrdir._ensure_real()
         bzrdir = bzrdir._real_bzrdir
@@ -325,7 +325,7 @@ def get_branch_info(branch):
     # XXX: Aaron Bentley 2008-06-13
     # Bazaar does not provide a public API for learning about
     # format markers.  Fix this in Bazaar, then here.
-    info['control_string'] = branch.bzrdir._format.get_format_string()
+    info['control_string'] = branch.controldir._format.get_format_string()
     info['branch_string'] = branch._format.get_format_string()
     info['repository_string'] = branch.repository._format.get_format_string()
     return info
diff --git a/lib/lp/codehosting/codeimport/tests/test_worker.py b/lib/lp/codehosting/codeimport/tests/test_worker.py
index 8bb5b7f..b414030 100644
--- a/lib/lp/codehosting/codeimport/tests/test_worker.py
+++ b/lib/lp/codehosting/codeimport/tests/test_worker.py
@@ -438,7 +438,7 @@ class TestImportDataStore(WorkerTest):
         remote_name = '%08x.tar.gz' % (source_details.target_id,)
         local_name = '%s.tar.gz' % (self.factory.getUniqueString(),)
         transport = self.get_transport()
-        transport.put_bytes(remote_name, '')
+        transport.put_bytes(remote_name, b'')
         store = ImportDataStore(transport, source_details)
         ret = store.fetch(local_name)
         self.assertTrue(ret)
@@ -496,7 +496,7 @@ class TestImportDataStore(WorkerTest):
         local_name = '%s.tar.gz' % (self.factory.getUniqueString(),)
         subdir_name = self.factory.getUniqueString()
         source_details = self.factory.makeCodeImportSourceDetails()
-        get_transport('.').put_bytes(local_name, '')
+        get_transport('.').put_bytes(local_name, b'')
         transport = self.get_transport()
         store = ImportDataStore(transport.clone(subdir_name), source_details)
         store.put(local_name)
diff --git a/lib/lp/codehosting/inmemory.py b/lib/lp/codehosting/inmemory.py
index bab222f..2873314 100644
--- a/lib/lp/codehosting/inmemory.py
+++ b/lib/lp/codehosting/inmemory.py
@@ -12,7 +12,7 @@ __all__ = [
 import operator
 from xmlrpclib import Fault
 
-from bzrlib.urlutils import (
+from breezy.urlutils import (
     escape,
     unescape,
     )
diff --git a/lib/lp/codehosting/puller/scheduler.py b/lib/lp/codehosting/puller/scheduler.py
index acbf014..35dd65b 100644
--- a/lib/lp/codehosting/puller/scheduler.py
+++ b/lib/lp/codehosting/puller/scheduler.py
@@ -320,7 +320,7 @@ class PullerMaster:
             self.default_stacked_on_url]
         self.logger.debug("executing %s", command)
         env = os.environ.copy()
-        env['BZR_EMAIL'] = get_lock_id_for_branch_id(self.branch_id)
+        env['BRZ_EMAIL'] = get_lock_id_for_branch_id(self.branch_id)
         reactor.spawnProcess(protocol, interpreter, command, env=env)
         return deferred
 
diff --git a/lib/lp/codehosting/puller/tests/__init__.py b/lib/lp/codehosting/puller/tests/__init__.py
index 716e2f5..59223a3 100644
--- a/lib/lp/codehosting/puller/tests/__init__.py
+++ b/lib/lp/codehosting/puller/tests/__init__.py
@@ -10,13 +10,13 @@ import shutil
 import socket
 from StringIO import StringIO
 
-from bzrlib.tests import TestCaseWithTransport
-from bzrlib.tests.http_server import (
+from breezy.tests import TestCaseWithTransport
+from breezy.tests.http_server import (
     HttpServer,
     TestingHTTPServer,
     TestingThreadingHTTPServer,
     )
-from bzrlib.url_policy_open import AcceptAnythingPolicy
+from breezy.url_policy_open import AcceptAnythingPolicy
 
 from lp.codehosting.puller.worker import (
     BranchMirrorer,
diff --git a/lib/lp/codehosting/puller/tests/test_acceptance.py b/lib/lp/codehosting/puller/tests/test_acceptance.py
index f835b65..305e52b 100644
--- a/lib/lp/codehosting/puller/tests/test_acceptance.py
+++ b/lib/lp/codehosting/puller/tests/test_acceptance.py
@@ -13,15 +13,15 @@ from subprocess import (
     Popen,
     )
 
-from bzrlib import errors
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDir
-from bzrlib.upgrade import upgrade
-from bzrlib.urlutils import (
+from breezy import errors
+from breezy.branch import Branch
+from breezy.bzr.bzrdir import BzrDir
+from breezy.upgrade import upgrade
+from breezy.urlutils import (
     join as urljoin,
     local_path_from_url,
     )
-from bzrlib.workingtree import WorkingTree
+from breezy.workingtree import WorkingTree
 from fixtures import TempDir
 import transaction
 from zope.component import getUtility
@@ -284,7 +284,7 @@ class TestBranchPuller(PullerBranchTestCase, LoomTestMixin):
         branch_url = urljoin(
             config.launchpad.bzr_imports_root_url, '%08x' % db_branch.id)
         branch = BzrDir.create_branch_convenience(branch_url)
-        tree = branch.bzrdir.open_workingtree()
+        tree = branch.controldir.open_workingtree()
         tree.commit('rev1')
 
         transaction.commit()
diff --git a/lib/lp/codehosting/puller/tests/test_errors.py b/lib/lp/codehosting/puller/tests/test_errors.py
index 9416799..1819e95 100644
--- a/lib/lp/codehosting/puller/tests/test_errors.py
+++ b/lib/lp/codehosting/puller/tests/test_errors.py
@@ -11,14 +11,14 @@ import socket
 import tempfile
 import urllib2
 
-from bzrlib.errors import (
+from breezy.errors import (
     BzrError,
     NotBranchError,
     ParamikoNotPresent,
     UnknownFormatError,
     UnsupportedFormatError,
     )
-from bzrlib.url_policy_open import (
+from breezy.url_policy_open import (
     BranchLoopError,
     BranchReferenceForbidden,
     )
diff --git a/lib/lp/codehosting/puller/tests/test_scheduler.py b/lib/lp/codehosting/puller/tests/test_scheduler.py
index df1d0c9..2b08509 100644
--- a/lib/lp/codehosting/puller/tests/test_scheduler.py
+++ b/lib/lp/codehosting/puller/tests/test_scheduler.py
@@ -7,12 +7,10 @@ import logging
 import os
 import textwrap
 
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import (
-    BzrDir,
-    format_registry,
-    )
-from bzrlib.urlutils import join as urljoin
+from breezy.branch import Branch
+from breezy.bzr.bzrdir import BzrDir
+from breezy.controldir import format_registry
+from breezy.urlutils import join as urljoin
 from testtools.twistedsupport import (
     assert_fails_with,
     AsynchronousDeferredRunTest,
@@ -545,7 +543,7 @@ parser = OptionParser()
 (options, arguments) = parser.parse_args()
 (source_url, destination_url, branch_id, unique_name,
  branch_type_name, default_stacked_on_url) = arguments
-from bzrlib import branch
+from breezy import branch
 branch = branch.Branch.open(destination_url)
 protocol = PullerWorkerProtocol(sys.stdout)
 """
@@ -865,7 +863,7 @@ class TestPullerMasterIntegration(PullerBranchTestCase):
         # We have to use a custom worker script to lower the time we wait for
         # the lock for (the default is five minutes, too long for a test!)
         lower_timeout_script = """
-        from bzrlib import lockdir
+        from breezy import lockdir
         lockdir._DEFAULT_TIMEOUT_SECONDS = 2.0
         from lp.code.enums import BranchType
         from lp.codehosting.puller.worker import (
diff --git a/lib/lp/codehosting/puller/tests/test_worker.py b/lib/lp/codehosting/puller/tests/test_worker.py
index d6cbaf3..addfcbb 100644
--- a/lib/lp/codehosting/puller/tests/test_worker.py
+++ b/lib/lp/codehosting/puller/tests/test_worker.py
@@ -8,21 +8,21 @@ __metaclass__ = type
 import gc
 from StringIO import StringIO
 
-import bzrlib.branch
-from bzrlib.branch import BranchReferenceFormat
-from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import (
+import breezy.branch
+from breezy.bzr.branch import BranchReferenceFormat
+from breezy.bzr.bzrdir import BzrDir
+from breezy.errors import (
     IncompatibleRepositories,
     NotBranchError,
     NotStacked,
     )
-from bzrlib.revision import NULL_REVISION
-from bzrlib.tests import (
+from breezy.revision import NULL_REVISION
+from breezy.tests import (
     TestCaseInTempDir,
     TestCaseWithTransport,
     )
-from bzrlib.transport import get_transport
-from bzrlib.url_policy_open import (
+from breezy.transport import get_transport
+from breezy.url_policy_open import (
     AcceptAnythingPolicy,
     BadUrl,
     BranchOpener,
@@ -124,7 +124,7 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
             source_tree.branch.base, self.get_url('dest'))
         source_tree.commit('commit message')
         to_mirror.mirrorWithoutChecks()
-        mirrored_branch = bzrlib.branch.Branch.open(to_mirror.dest)
+        mirrored_branch = breezy.branch.Branch.open(to_mirror.dest)
         self.assertEqual(
             source_tree.last_revision(), mirrored_branch.last_revision())
 
@@ -134,7 +134,7 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
         to_mirror = self.makePullerWorker(
             source_branch.base, self.get_url('dest'))
         to_mirror.mirrorWithoutChecks()
-        mirrored_branch = bzrlib.branch.Branch.open(to_mirror.dest)
+        mirrored_branch = breezy.branch.Branch.open(to_mirror.dest)
         self.assertEqual(NULL_REVISION, mirrored_branch.last_revision())
 
     def testCanMirrorWhenDestDirExists(self):
@@ -150,9 +150,9 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
         dest.mkdir('.bzr')
         # 'dest' is not a branch.
         self.assertRaises(
-            NotBranchError, bzrlib.branch.Branch.open, to_mirror.dest)
+            NotBranchError, breezy.branch.Branch.open, to_mirror.dest)
         to_mirror.mirrorWithoutChecks()
-        mirrored_branch = bzrlib.branch.Branch.open(to_mirror.dest)
+        mirrored_branch = breezy.branch.Branch.open(to_mirror.dest)
         self.assertEqual(
             source_tree.last_revision(), mirrored_branch.last_revision())
 
@@ -179,7 +179,7 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
             source_branch.base, self.get_url('destdir'),
             policy=PrearrangedStackedBranchPolicy(stack_on.base))
         to_mirror.mirrorWithoutChecks()
-        dest = bzrlib.branch.Branch.open(self.get_url('destdir'))
+        dest = breezy.branch.Branch.open(self.get_url('destdir'))
         self.assertFalse(dest._format.supports_stacking())
 
     def test_defaultStackedOnBranchIncompatibleMirrorsOK(self):
@@ -192,7 +192,7 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
             source_branch.base, self.get_url('destdir'),
             policy=PrearrangedStackedBranchPolicy(stack_on.base))
         to_mirror.mirrorWithoutChecks()
-        dest = bzrlib.branch.Branch.open(self.get_url('destdir'))
+        dest = breezy.branch.Branch.open(self.get_url('destdir'))
         self.assertRaises(NotStacked, dest.get_stacked_on_url)
 
     def testCanMirrorWithIncompatibleRepos(self):
@@ -212,7 +212,7 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
         # IncompatibleRepositories.
         self.assertRaises(
             IncompatibleRepositories,
-            bzrlib.branch.Branch.open, 'dest/stacked')
+            breezy.branch.Branch.open, 'dest/stacked')
         source_branch = self.make_branch(
             'source-branch', format='2a')
         to_mirror = self.makePullerWorker(
@@ -220,7 +220,7 @@ class TestPullerWorker(TestCaseWithTransport, PullerWorkerMixin):
         # The branch can be mirrored without errors and the destionation
         # location is upgraded to match the source format.
         to_mirror.mirrorWithoutChecks()
-        mirrored_branch = bzrlib.branch.Branch.open(to_mirror.dest)
+        mirrored_branch = breezy.branch.Branch.open(to_mirror.dest)
         self.assertEqual(
             source_branch.repository._format,
             mirrored_branch.repository._format)
@@ -286,7 +286,7 @@ class TestReferenceOpener(TestCaseWithTransport):
         :return: file url to the created pure branch reference.
         """
         # XXX DavidAllouche 2007-09-12 bug=139109:
-        # We do this manually because the bzrlib API does not support creating
+        # We do this manually because the breezy API does not support creating
         # a branch reference without opening it.
         t = get_transport(self.get_url('.'))
         t.mkdir('reference')
@@ -314,7 +314,7 @@ class TestReferenceOpener(TestCaseWithTransport):
 
         # Open the branch reference and check that the result is indeed the
         # branch we wanted it to point at.
-        opened_branch = bzrlib.branch.Branch.open(reference_url)
+        opened_branch = breezy.branch.Branch.open(reference_url)
         self.assertEqual(opened_branch.base, target_branch.base)
 
     def testFollowReferenceValue(self):
@@ -496,9 +496,9 @@ class TestWorkerProgressReporting(TestCaseWithTransport):
     def setUp(self):
         super(TestWorkerProgressReporting, self).setUp()
         BranchOpener.install_hook()
-        self.saved_factory = bzrlib.ui.ui_factory
+        self.saved_factory = breezy.ui.ui_factory
         self.disable_directory_isolation()
-        self.addCleanup(setattr, bzrlib.ui, 'ui_factory', self.saved_factory)
+        self.addCleanup(setattr, breezy.ui, 'ui_factory', self.saved_factory)
 
     def getHttpServerForCwd(self):
         """Get an `HttpServer` instance that serves from '.'."""
@@ -530,7 +530,7 @@ class TestWorkerProgressReporting(TestCaseWithTransport):
 
         p = self.StubProtocol()
         install_worker_ui_factory(p)
-        b2_http = bzrlib.branch.Branch.open(
+        b2_http = breezy.branch.Branch.open(
             http_server.get_url() + 'some-other-branch')
         b1.pull(b2_http)
         self.assertSubset([WORKER_ACTIVITY_NETWORK], p.calls)
diff --git a/lib/lp/codehosting/puller/tests/test_worker_formats.py b/lib/lp/codehosting/puller/tests/test_worker_formats.py
index 3cc8873..b065ffa 100644
--- a/lib/lp/codehosting/puller/tests/test_worker_formats.py
+++ b/lib/lp/codehosting/puller/tests/test_worker_formats.py
@@ -5,19 +5,19 @@
 
 __metaclass__ = type
 
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDirMetaFormat1
-from bzrlib.plugins.weave_fmt.bzrdir import BzrDirFormat6
-from bzrlib.plugins.weave_fmt.repository import (
+from breezy.branch import Branch
+from breezy.bzr.bzrdir import BzrDirMetaFormat1
+from breezy.bzr.knitpack_repo import RepositoryFormatKnitPack5
+from breezy.bzr.knitrepo import RepositoryFormatKnit1
+from breezy.plugins.weave_fmt.bzrdir import BzrDirFormat6
+from breezy.plugins.weave_fmt.repository import (
     RepositoryFormat6,
     RepositoryFormat7,
     )
-from bzrlib.repofmt.knitpack_repo import RepositoryFormatKnitPack5
-from bzrlib.repofmt.knitrepo import RepositoryFormatKnit1
-from bzrlib.tests.per_repository import TestCaseWithRepository
-from bzrlib.url_policy_open import BranchOpener
+from breezy.tests.per_repository import TestCaseWithRepository
+from breezy.url_policy_open import BranchOpener
 
-import lp.codehosting  # For bzr plugins.
+import lp.codehosting  # For brz plugins.
 from lp.codehosting.puller.tests import PullerWorkerMixin
 from lp.codehosting.tests.helpers import LoomTestMixin
 
@@ -27,7 +27,7 @@ class TestPullerWorkerFormats(TestCaseWithRepository, PullerWorkerMixin,
 
     def setUp(self):
         TestCaseWithRepository.setUp(self)
-        # make_bzrdir relies on this being a relative filesystem path.
+        # make_controldir relies on this being a relative filesystem path.
         self._source_branch_path = 'source-branch'
         BranchOpener.install_hook()
         self.worker = self.makePullerWorker(
@@ -39,7 +39,8 @@ class TestPullerWorkerFormats(TestCaseWithRepository, PullerWorkerMixin,
         """Make a source branch with the given formats."""
         if branch_format is not None:
             bzrdir_format.set_branch_format(branch_format)
-        bd = self.make_bzrdir(self._source_branch_path, format=bzrdir_format)
+        bd = self.make_controldir(
+            self._source_branch_path, format=bzrdir_format)
         repository_format.initialize(bd)
         branch = bd.create_branch()
         tree = branch.create_checkout('source-checkout')
@@ -58,8 +59,8 @@ class TestPullerWorkerFormats(TestCaseWithRepository, PullerWorkerMixin,
             source_branch.repository._format.get_format_description(),
             dest_branch.repository._format.get_format_description())
         self.assertEqual(
-            source_branch.bzrdir._format.get_format_description(),
-            dest_branch.bzrdir._format.get_format_description())
+            source_branch.controldir._format.get_format_description(),
+            dest_branch.controldir._format.get_format_description())
 
     def _testMirrorWithFormats(self, repository_format, bzrdir_format):
         """Make a branch with certain formats, mirror it and check the mirror.
@@ -85,9 +86,8 @@ class TestPullerWorkerFormats(TestCaseWithRepository, PullerWorkerMixin,
         self.assertMirrored(branch, mirrored_branch)
 
     # XXX: JonathanLange 2008-06-25: These next three tests should be
-    # implemented against all supported repository formats using bzrlib's test
-    # adaptation APIs. Unfortunately, this API changes between 1.5 and 1.6, so
-    # it'd be a bit silly to do the work now.
+    # implemented against all supported repository formats using breezy's test
+    # adaptation APIs.
     def testMirrorKnitAsKnit(self):
         # Create a source branch in knit format, and check that the mirror is
         # in knit format.
diff --git a/lib/lp/codehosting/puller/worker.py b/lib/lp/codehosting/puller/worker.py
index e0ff5b4..d0ed4ca 100644
--- a/lib/lp/codehosting/puller/worker.py
+++ b/lib/lp/codehosting/puller/worker.py
@@ -12,22 +12,25 @@ import urllib2
 # line below this comment.
 import lp.codehosting
 
-from bzrlib import (
+from breezy import (
     errors,
     urlutils,
     )
-from bzrlib.branch import Branch
-from bzrlib.plugins.loom.branch import LoomSupport
-from bzrlib.plugins.weave_fmt.branch import BzrBranchFormat4
-from bzrlib.plugins.weave_fmt.repository import (
+from breezy.branch import (
+    Branch,
+    UnstackableBranchFormat,
+    )
+from breezy.plugins.loom.branch import LoomSupport
+from breezy.plugins.weave_fmt.branch import BzrBranchFormat4
+from breezy.plugins.weave_fmt.repository import (
     RepositoryFormat4,
     RepositoryFormat5,
     RepositoryFormat6,
     )
-from bzrlib.transport import get_transport
-import bzrlib.ui
-from bzrlib.ui import SilentUIFactory
-from bzrlib.url_policy_open import (
+from breezy.transport import get_transport
+import breezy.ui
+from breezy.ui import SilentUIFactory
+from breezy.url_policy_open import (
     BadUrl,
     BranchLoopError,
     BranchOpener,
@@ -158,7 +161,7 @@ class BranchMirrorerPolicy(BranchOpenPolicy):
             revision_id = None
         else:
             revision_id = 'null:'
-        source_branch.bzrdir.clone_on_transport(
+        source_branch.controldir.clone_on_transport(
             dest_transport, revision_id=revision_id)
         return Branch.open(destination_url)
 
@@ -251,7 +254,7 @@ class BranchMirrorer(object):
         try:
             dest_branch.set_stacked_on_url(stacked_on_url)
         except (errors.UnstackableRepositoryFormat,
-                errors.UnstackableBranchFormat,
+                UnstackableBranchFormat,
                 errors.IncompatibleRepositories):
             stacked_on_url = None
         if stacked_on_url is None:
@@ -448,7 +451,7 @@ class PullerWorker:
             # XXX: Aaron Bentley 2008-06-13
             # Bazaar does not provide a public API for learning about
             # format markers.  Fix this in Bazaar, then here.
-            control_string = dest_branch.bzrdir._format.get_format_string()
+            control_string = dest_branch.controldir._format.get_format_string()
             if dest_branch._format.__class__ is BzrBranchFormat4:
                 branch_string = BranchFormat.BZR_BRANCH_4.title
             else:
@@ -488,8 +491,10 @@ class PullerWorkerUIFactory(SilentUIFactory):
     def confirm_action(self, prompt, confirmation_id, args):
         """If we're asked to break a lock like a stale lock of ours, say yes.
         """
-        assert confirmation_id == 'bzrlib.lockdir.break', \
-            "Didn't expect confirmation id %r" % (confirmation_id,)
+        if confirmation_id not in (
+                'bzrlib.lockdir.break', 'breezy.lockdir.break'):
+            raise AssertionError(
+                "Didn't expect confirmation id %r" % (confirmation_id,))
         branch_id = self.puller_worker_protocol.branch_id
         prompt = prompt % args
         if get_lock_id_for_branch_id(branch_id) in prompt:
@@ -518,7 +523,7 @@ def install_worker_ui_factory(puller_worker_protocol):
     2) Break locks if and only if they appear to be stale locks
        created by another puller worker process.
     """
-    bzrlib.ui.ui_factory = PullerWorkerUIFactory(puller_worker_protocol)
+    breezy.ui.ui_factory = PullerWorkerUIFactory(puller_worker_protocol)
 
 
 class MirroredBranchPolicy(BranchMirrorerPolicy):
@@ -600,7 +605,7 @@ class ImportedBranchPolicy(BranchMirrorerPolicy):
         Because we control the process that creates import branches, a
         vfs-level copy is safe and more efficient than a bzr fetch.
         """
-        source_transport = source_branch.bzrdir.root_transport
+        source_transport = source_branch.controldir.root_transport
         dest_transport = get_transport(destination_url)
         while True:
             # We loop until the remote file list before and after the copy is
diff --git a/lib/lp/codehosting/rewrite.py b/lib/lp/codehosting/rewrite.py
index c6e204d..f59520b 100644
--- a/lib/lp/codehosting/rewrite.py
+++ b/lib/lp/codehosting/rewrite.py
@@ -6,7 +6,7 @@
 
 import time
 
-from bzrlib import urlutils
+from breezy import urlutils
 from zope.component import getUtility
 from zope.security.interfaces import Unauthorized
 
diff --git a/lib/lp/codehosting/scanner/buglinks.py b/lib/lp/codehosting/scanner/buglinks.py
index 539bd93..95d8eaa 100644
--- a/lib/lp/codehosting/scanner/buglinks.py
+++ b/lib/lp/codehosting/scanner/buglinks.py
@@ -10,7 +10,7 @@ __all__ = [
 
 import urlparse
 
-from bzrlib.errors import InvalidBugStatus
+from breezy.bugtracker import InvalidBugStatus
 from zope.component import getUtility
 
 from lp.app.errors import NotFoundError
diff --git a/lib/lp/codehosting/scanner/bzrsync.py b/lib/lp/codehosting/scanner/bzrsync.py
index 0161972..4eab1a9 100755
--- a/lib/lp/codehosting/scanner/bzrsync.py
+++ b/lib/lp/codehosting/scanner/bzrsync.py
@@ -16,8 +16,8 @@ __all__ = [
 
 import logging
 
-from bzrlib.graph import DictParentsProvider
-from bzrlib.revision import NULL_REVISION
+from breezy.graph import DictParentsProvider
+from breezy.revision import NULL_REVISION
 import pytz
 import six
 from storm.locals import Store
@@ -91,7 +91,7 @@ class BzrSync:
         self.logger.info("    from %s", bzr_branch.base)
         # Get the history and ancestry from the branch first, to fail early
         # if something is wrong with the branch.
-        self.logger.info("Retrieving history from bzrlib.")
+        self.logger.info("Retrieving history from breezy.")
         bzr_history = branch_revision_history(bzr_branch)
         # The BranchRevision, Revision and RevisionParent tables are only
         # written to by the branch-scanner, so they are not subject to
@@ -197,7 +197,7 @@ class BzrSync:
 
     def planDatabaseChanges(self, bzr_branch, bzr_history, db_ancestry,
                             db_history):
-        """Plan database changes to synchronize with bzrlib data.
+        """Plan database changes to synchronize with breezy data.
 
         Use the data retrieved by `retrieveDatabaseAncestry` and
         `retrieveBranchDetails` to plan the changes to apply to the database.
@@ -240,7 +240,7 @@ class BzrSync:
     def getBazaarRevisions(self, bzr_branch, revisions):
         """Like ``get_revisions(revisions)`` but filter out ghosts first.
 
-        :param revisions: the set of Bazaar revision IDs to return bzrlib
+        :param revisions: the set of Breezy revision IDs to return breezy
             Revision objects for.
         """
         revisions = bzr_branch.repository.get_parent_map(revisions)
@@ -249,9 +249,9 @@ class BzrSync:
     def syncRevisions(self, bzr_branch, bzr_revisions, revids_to_insert):
         """Import the supplied revisions.
 
-        :param bzr_branch: The Bazaar branch that's being scanned.
+        :param bzr_branch: The Breezy branch that's being scanned.
         :param bzr_revisions: the revisions to import
-        :type bzr_revision: bzrlib.revision.Revision
+        :type bzr_revision: breezy.revision.Revision
         :param revids_to_insert: a dict of revision ids to integer
             revno. Non-mainline revisions will be mapped to None.
         """
diff --git a/lib/lp/codehosting/scanner/mergedetection.py b/lib/lp/codehosting/scanner/mergedetection.py
index db23fdb..0e5dcd5 100644
--- a/lib/lp/codehosting/scanner/mergedetection.py
+++ b/lib/lp/codehosting/scanner/mergedetection.py
@@ -9,7 +9,7 @@ __all__ = [
     'auto_merge_proposals',
     ]
 
-from bzrlib.revision import NULL_REVISION
+from breezy.revision import NULL_REVISION
 from zope.component import getUtility
 
 from lp.code.adapters.branch import BranchMergeProposalNoPreviewDiffDelta
diff --git a/lib/lp/codehosting/scanner/tests/test_buglinks.py b/lib/lp/codehosting/scanner/tests/test_buglinks.py
index bfa2981..935af50 100644
--- a/lib/lp/codehosting/scanner/tests/test_buglinks.py
+++ b/lib/lp/codehosting/scanner/tests/test_buglinks.py
@@ -1,11 +1,11 @@
 # Copyright 2009 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""Tests for creating BugBranch items based on Bazaar revisions."""
+"""Tests for creating BugBranch items based on Breezy revisions."""
 
 __metaclass__ = type
 
-from bzrlib.revision import Revision
+from breezy.revision import Revision
 from zope.component import getUtility
 from zope.event import notify
 
@@ -192,7 +192,7 @@ class TestBugLinking(BzrSyncTestCase):
         author = self.factory.getUniqueString()
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             self.bzr_tree.commit(
                 u'common parent', committer=author, rev_id='r1',
                 allow_pointless=True)
@@ -253,7 +253,7 @@ class TestSubscription(TestCaseWithFactory):
         switch_dbuser("branchscanner")
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             revision_id = tree.commit('fix revision',
                 revprops={
                     'bugs': 'https://launchpad.net/bugs/%d fixed' % bug.id})
diff --git a/lib/lp/codehosting/scanner/tests/test_bzrsync.py b/lib/lp/codehosting/scanner/tests/test_bzrsync.py
index 660d101..9ddc355 100644
--- a/lib/lp/codehosting/scanner/tests/test_bzrsync.py
+++ b/lib/lp/codehosting/scanner/tests/test_bzrsync.py
@@ -8,13 +8,13 @@ import os
 import random
 import time
 
-from bzrlib.revision import (
+from breezy.revision import (
     NULL_REVISION,
     Revision as BzrRevision,
     )
-from bzrlib.tests import TestCaseWithTransport
-from bzrlib.uncommit import uncommit
-from bzrlib.url_policy_open import BranchOpener
+from breezy.tests import TestCaseWithTransport
+from breezy.uncommit import uncommit
+from breezy.url_policy_open import BranchOpener
 from fixtures import (
     FakeLogger,
     TempDir,
@@ -191,7 +191,7 @@ class BzrSyncTestCase(TestCaseWithTransport, TestCaseWithFactory):
             self.bzr_tree.add_pending_merge(*extra_parents)
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             return self.bzr_tree.commit(
                 message, committer=committer, rev_id=rev_id,
                 timestamp=timestamp, timezone=timezone, allow_pointless=True,
@@ -240,7 +240,7 @@ class BzrSyncTestCase(TestCaseWithTransport, TestCaseWithFactory):
                 db_branch=db_branch)
             # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
             # required to generate the revision-id.
-            with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+            with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
                 trunk_tree.commit(u'base revision', rev_id=base_rev_id)
 
                 # Branch from the base revision.
@@ -572,7 +572,8 @@ class TestPlanDatabaseChanges(BzrSyncTestCase):
         # deletion anyway.
         rev1_id = self.bzr_tree.commit(
             'initial commit', committer='me@xxxxxxxxxxx')
-        merge_tree = self.bzr_tree.bzrdir.sprout('merge').open_workingtree()
+        merge_tree = self.bzr_tree.controldir.sprout(
+            'merge').open_workingtree()
         merge_id = merge_tree.commit(
             'mergeable commit', committer='me@xxxxxxxxxxx')
         self.bzr_tree.merge_from_branch(merge_tree.branch)
diff --git a/lib/lp/codehosting/scanner/tests/test_email.py b/lib/lp/codehosting/scanner/tests/test_email.py
index 39ccec3..a403251 100644
--- a/lib/lp/codehosting/scanner/tests/test_email.py
+++ b/lib/lp/codehosting/scanner/tests/test_email.py
@@ -8,7 +8,7 @@ __metaclass__ = type
 import email
 import os
 
-from bzrlib.uncommit import uncommit
+from breezy.uncommit import uncommit
 from zope.component import getUtility
 from zope.event import notify
 
diff --git a/lib/lp/codehosting/scanner/tests/test_mergedetection.py b/lib/lp/codehosting/scanner/tests/test_mergedetection.py
index 3d4508e..c0cb7ad 100644
--- a/lib/lp/codehosting/scanner/tests/test_mergedetection.py
+++ b/lib/lp/codehosting/scanner/tests/test_mergedetection.py
@@ -7,7 +7,7 @@ __metaclass__ = type
 
 import logging
 
-from bzrlib.revision import NULL_REVISION
+from breezy.revision import NULL_REVISION
 from lazr.lifecycle.event import ObjectModifiedEvent
 import transaction
 from zope.component import getUtility
@@ -143,7 +143,7 @@ class TestAutoMergeDetectionForMergeProposals(BzrSyncTestCase):
 
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             branch_tree.commit(u'another revision', rev_id='another-rev')
         current_proposal_status = proposal.queue_status
         self.assertNotEqual(
@@ -164,7 +164,7 @@ class TestAutoMergeDetectionForMergeProposals(BzrSyncTestCase):
 
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             branch_tree.commit(u'another revision', rev_id='another-rev')
         current_proposal_status = proposal.queue_status
         self.assertNotEqual(
diff --git a/lib/lp/codehosting/scripts/tests/test_upgrade_all_branches.py b/lib/lp/codehosting/scripts/tests/test_upgrade_all_branches.py
index b820539..5f9443f 100644
--- a/lib/lp/codehosting/scripts/tests/test_upgrade_all_branches.py
+++ b/lib/lp/codehosting/scripts/tests/test_upgrade_all_branches.py
@@ -8,7 +8,7 @@ import logging
 import os
 from os.path import dirname
 
-from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2a
+from breezy.bzr.groupcompress_repo import RepositoryFormat2a
 from fixtures import TempDir
 import transaction
 
diff --git a/lib/lp/codehosting/sftp.py b/lib/lp/codehosting/sftp.py
index 4c7e7fb..51d42e7 100644
--- a/lib/lp/codehosting/sftp.py
+++ b/lib/lp/codehosting/sftp.py
@@ -24,12 +24,12 @@ import errno
 import os
 import stat
 
-from bzrlib import (
+from breezy import (
     errors as bzr_errors,
     osutils,
     urlutils,
     )
-from bzrlib.transport.local import LocalTransport
+from breezy.transport.local import LocalTransport
 from lazr.sshserver.sftp import FileIsADirectory
 from twisted.conch.interfaces import (
     ISFTPFile,
@@ -160,7 +160,7 @@ class TransportSFTPFile:
     def _truncateFile(self):
         """Truncate this file."""
         self._written = True
-        return self.transport.put_bytes(self._escaped_path, '')
+        return self.transport.put_bytes(self._escaped_path, b'')
 
     @with_sftp_error
     def writeChunk(self, offset, data):
@@ -198,7 +198,7 @@ class TransportSFTPFile:
 
             Doing things this way around, by trying to read all the data
             requested and then handling the short read error, might be a bit
-            inefficient, but the bzrlib sftp transport doesn't read past the
+            inefficient, but the breezy sftp transport doesn't read past the
             end of files, so we don't need to worry too much about performance
             here.
             """
diff --git a/lib/lp/codehosting/sshserver/session.py b/lib/lp/codehosting/sshserver/session.py
index 64567fe..91d31e4 100644
--- a/lib/lp/codehosting/sshserver/session.py
+++ b/lib/lp/codehosting/sshserver/session.py
@@ -26,7 +26,7 @@ from twisted.python import log
 from zope.event import notify
 from zope.interface import implementer
 
-from lp.codehosting import get_bzr_path
+from lp.codehosting import get_brz_path
 from lp.services.config import config
 
 
@@ -141,16 +141,17 @@ class ForkedProcessTransport(process.BaseProcess):
 
         :return: The pid, communication directory, and request socket.
         """
-        assert executable == 'bzr', executable  # Maybe .endswith()
-        assert args[0] == 'bzr', args[0]
+        assert executable == 'brz', executable  # Maybe .endswith()
+        assert args[0] == 'brz', args[0]
         message = ['fork-env %s\n' % (' '.join(args[1:]),)]
         for key, value in environment.iteritems():
-            # XXX: Currently we only pass BZR_EMAIL, should we be passing
+            # XXX: Currently we only pass BRZ_EMAIL, should we be passing
             #      everything else? Note that many won't be handled properly,
             #      since the process is already running.
-            if key != 'BZR_EMAIL':
-                continue
-            message.append('%s: %s\n' % (key, value))
+            if key in ('BZR_EMAIL', 'BRZ_EMAIL'):
+                # Map both of these to BRZ_EMAIL, since we run brz on the
+                # server.
+                message.append('BRZ_EMAIL: %s\n' % (value,))
         message.append('end\n')
         message = ''.join(message)
         response, sock = self._sendMessageToService(message)
@@ -418,7 +419,7 @@ class ForkingRestrictedExecOnlySession(RestrictedExecOnlySession):
     def _simplifyEnvironment(self, env):
         """Pull out the bits of the environment we want to pass along."""
         env = {}
-        for env_var in ['BZR_EMAIL']:
+        for env_var in ['BRZ_EMAIL']:
             if env_var in self.environment:
                 env[env_var] = self.environment[env_var]
         return env
@@ -426,15 +427,15 @@ class ForkingRestrictedExecOnlySession(RestrictedExecOnlySession):
     def getCommandToFork(self, executable, arguments, env):
         assert executable.endswith('/bin/py')
         assert arguments[0] == executable
-        assert arguments[1].endswith('/bzr')
-        executable = 'bzr'
+        assert arguments[1].endswith('/brz')
+        executable = 'brz'
         arguments = arguments[1:]
-        arguments[0] = 'bzr'
+        arguments[0] = 'brz'
         env = self._simplifyEnvironment(env)
         return executable, arguments, env
 
     def _spawn(self, protocol, executable, arguments, env):
-        # When spawning, adapt the idea of "bin/py .../bzr" to just using "bzr"
+        # When spawning, adapt the idea of "bin/py .../brz" to just using "brz"
         # and the executable
         executable, arguments, env = self.getCommandToFork(executable,
                                                            arguments, env)
@@ -449,16 +450,18 @@ def lookup_command_template(command):
     :return: Command template
     :raise ForbiddenCommand: Raised when command isn't allowed
     """
-    python_command = "%(root)s/bin/py %(bzr)s" % {
+    python_command = "%(root)s/bin/py %(brz)s" % {
             'root': config.root,
-            'bzr': get_bzr_path(),
+            'brz': get_brz_path(),
             }
     args = " lp-serve --inet %(user_id)s"
     command_template = python_command + args
 
-    if command == 'bzr serve --inet --directory=/ --allow-writes':
+    if command in (
+            'bzr serve --inet --directory=/ --allow-writes',
+            'brz serve --inet --directory=/ --allow-writes'):
         return command_template
-    # At the moment, only bzr branch serving is allowed.
+    # At the moment, only bzr/brz branch serving is allowed.
     raise ForbiddenCommand("Not allowed to execute %r." % (command,))
 
 
@@ -469,7 +472,7 @@ def launch_smart_server(avatar):
 
     # Extract the hostname from the supermirror root config.
     hostname = urlparse.urlparse(config.codehosting.supermirror_root)[1]
-    environment['BZR_EMAIL'] = '%s@%s' % (avatar.username, hostname)
+    environment['BRZ_EMAIL'] = '%s@%s' % (avatar.username, hostname)
     # TODO: Use a FeatureFlag to enable this in a more fine-grained approach.
     #       If the forking daemon has been spawned, then we can use it if the
     #       feature is set to true for the given user, etc.
diff --git a/lib/lp/codehosting/sshserver/tests/test_session.py b/lib/lp/codehosting/sshserver/tests/test_session.py
index 7b1ad2f..a212873 100644
--- a/lib/lp/codehosting/sshserver/tests/test_session.py
+++ b/lib/lp/codehosting/sshserver/tests/test_session.py
@@ -13,8 +13,8 @@ from twisted.internet.process import ProcessExitedAlready
 from twisted.internet.protocol import ProcessProtocol
 
 from lp.codehosting import (
-    get_bzr_path,
-    get_BZR_PLUGIN_PATH_for_subprocess,
+    get_brz_path,
+    get_BRZ_PLUGIN_PATH_for_subprocess,
     )
 from lp.codehosting.sshserver.daemon import CodehostingAvatar
 from lp.codehosting.sshserver.session import (
@@ -382,18 +382,18 @@ class TestSessionIntegration(AvatarTestCase):
             "ISession(avatar) doesn't adapt to ExecOnlySession. "
             "Got %r instead." % (session,))
         self.assertEqual(
-            get_BZR_PLUGIN_PATH_for_subprocess(),
-            session.environment['BZR_PLUGIN_PATH'])
+            get_BRZ_PLUGIN_PATH_for_subprocess(),
+            session.environment['BRZ_PLUGIN_PATH'])
         self.assertEqual(
             '%s@xxxxxxxxxxxxxxxxxxxxx' % self.avatar.username,
-            session.environment['BZR_EMAIL'])
+            session.environment['BRZ_EMAIL'])
 
         executable, arguments = session.getCommandToRun(
             'bzr serve --inet --directory=/ --allow-writes')
         interpreter = '%s/bin/py' % config.root
         self.assertEqual(interpreter, executable)
         self.assertEqual(
-            [interpreter, get_bzr_path(), 'lp-serve',
+            [interpreter, get_brz_path(), 'lp-serve',
              '--inet', str(self.avatar.user_id)],
             list(arguments))
         self.assertRaises(
@@ -422,9 +422,9 @@ class TestSessionIntegration(AvatarTestCase):
             'bzr serve --inet --directory=/ --allow-writes')
         executable, arguments, env = session.getCommandToFork(
             executable, arguments, session.environment)
-        self.assertEqual('bzr', executable)
+        self.assertEqual('brz', executable)
         self.assertEqual(
-             ['bzr', 'lp-serve',
+             ['brz', 'lp-serve',
               '--inet', str(self.avatar.user_id)],
              list(arguments))
 
@@ -436,7 +436,14 @@ class TestLookupCommand(TestCase):
 
     def test_bzr(self):
         self.assertEqual(
-            config.root + '/bin/py ' + get_bzr_path() +
+            config.root + '/bin/py ' + get_brz_path() +
             ' lp-serve --inet %(user_id)s',
             lookup_command_template(
                 'bzr serve --inet --directory=/ --allow-writes'))
+
+    def test_brz(self):
+        self.assertEqual(
+            config.root + '/bin/py ' + get_brz_path() +
+            ' lp-serve --inet %(user_id)s',
+            lookup_command_template(
+                'brz serve --inet --directory=/ --allow-writes'))
diff --git a/lib/lp/codehosting/tests/helpers.py b/lib/lp/codehosting/tests/helpers.py
index e278e53..71d4a52 100644
--- a/lib/lp/codehosting/tests/helpers.py
+++ b/lib/lp/codehosting/tests/helpers.py
@@ -15,10 +15,9 @@ __all__ = [
 
 import os
 
-from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import FileExists
-from bzrlib.plugins.loom import branch as loom_branch
-from bzrlib.tests import (
+from breezy.errors import FileExists
+from breezy.plugins.loom import branch as loom_branch
+from breezy.tests import (
     TestNotApplicable,
     TestSkipped,
     )
@@ -60,7 +59,7 @@ class LoomTestMixin:
             loom_branch.loomify(tree.branch)
         finally:
             tree.unlock()
-        loom_tree = tree.bzrdir.open_workingtree()
+        loom_tree = tree.controldir.open_workingtree()
         loom_tree.lock_write()
         loom_tree.branch.new_thread('bottom-thread')
         loom_tree.commit('this is a commit', rev_id='commit-1')
@@ -78,7 +77,7 @@ class LoomTestMixin:
             loom_branch.loomify(tree.branch)
         finally:
             tree.unlock()
-        loom_tree = tree.bzrdir.open_workingtree()
+        loom_tree = tree.controldir.open_workingtree()
         loom_tree.lock_write()
         loom_tree.branch.new_thread('bottom-thread')
         loom_tree.commit('this is a commit', rev_id='commit-1')
@@ -100,6 +99,9 @@ def make_bazaar_branch_and_tree(db_branch):
 
 def create_branch_with_one_revision(branch_dir, format=None):
     """Create a dummy Bazaar branch at the given directory."""
+    # XXX cjwatson 2019-06-13: This still uses bzrlib until such time as the
+    # code import workers are ported to Breezy.
+    from bzrlib.bzrdir import BzrDir
     if not os.path.exists(branch_dir):
         os.makedirs(branch_dir)
     try:
@@ -124,7 +126,7 @@ def force_stacked_on_url(branch, url):
 
 
 class TestResultWrapper:
-    """A wrapper for `TestResult` that knows about bzrlib's `TestSkipped`."""
+    """A wrapper for `TestResult` that knows about breezy's `TestSkipped`."""
 
     def __init__(self, result):
         self.result = result
diff --git a/lib/lp/codehosting/tests/servers.py b/lib/lp/codehosting/tests/servers.py
index 99006c0..68c4a73 100644
--- a/lib/lp/codehosting/tests/servers.py
+++ b/lib/lp/codehosting/tests/servers.py
@@ -15,7 +15,7 @@ import os
 import shutil
 import tempfile
 
-from bzrlib.transport import (
+from breezy.transport import (
     get_transport,
     Server,
     )
diff --git a/lib/lp/codehosting/tests/test_acceptance.py b/lib/lp/codehosting/tests/test_acceptance.py
index d840ebf..1b4e1bf 100644
--- a/lib/lp/codehosting/tests/test_acceptance.py
+++ b/lib/lp/codehosting/tests/test_acceptance.py
@@ -14,11 +14,11 @@ import time
 import urllib2
 import xmlrpclib
 
-import bzrlib.branch
-from bzrlib.tests import TestCaseWithTransport
-from bzrlib.tests.per_repository import all_repository_format_scenarios
-from bzrlib.urlutils import local_path_from_url
-from bzrlib.workingtree import WorkingTree
+import breezy.branch
+from breezy.tests import TestCaseWithTransport
+from breezy.tests.per_repository import all_repository_format_scenarios
+from breezy.urlutils import local_path_from_url
+from breezy.workingtree import WorkingTree
 from testscenarios import (
     load_tests_apply_scenarios,
     WithScenarios,
@@ -37,8 +37,8 @@ from lp.code.tests.helpers import (
     get_non_existant_source_package_branch_unique_name,
     )
 from lp.codehosting import (
-    get_bzr_path,
-    get_BZR_PLUGIN_PATH_for_subprocess,
+    get_brz_path,
+    get_BRZ_PLUGIN_PATH_for_subprocess,
     )
 from lp.codehosting.bzrutils import DenyingServer
 from lp.codehosting.tests.helpers import LoomTestMixin
@@ -64,10 +64,10 @@ class ForkingServerForTests(object):
         self.socket_path = None
 
     def setUp(self):
-        bzr_path = get_bzr_path()
-        BZR_PLUGIN_PATH = get_BZR_PLUGIN_PATH_for_subprocess()
+        brz_path = get_brz_path()
+        BRZ_PLUGIN_PATH = get_BRZ_PLUGIN_PATH_for_subprocess()
         env = os.environ.copy()
-        env['BZR_PLUGIN_PATH'] = BZR_PLUGIN_PATH
+        env['BRZ_PLUGIN_PATH'] = BRZ_PLUGIN_PATH
         # TODO: We probably want to use a random disk path for
         #       forking_daemon_socket, but we need to update config so that
         #       the CodeHosting service can find it.
@@ -77,7 +77,7 @@ class ForkingServerForTests(object):
         #       settings, we have to somehow pass it a new config-on-disk to
         #       use.
         self.socket_path = config.codehosting.forking_daemon_socket
-        command = [sys.executable, bzr_path, 'launchpad-forking-service',
+        command = [sys.executable, brz_path, 'launchpad-forking-service',
                    '--path', self.socket_path, '-Derror']
         process = subprocess.Popen(
             command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
@@ -110,12 +110,12 @@ class ForkingServerForTests(object):
             print process.stderr.read()
             print "-" * 70
             raise RuntimeError(
-                'Bzr server did not start correctly.  See stdout and stderr '
-                'reported above. Command was "%s".  PYTHONPATH was "%s".  '
-                'BZR_PLUGIN_PATH was "%s".' %
+                'Breezy server did not start correctly.  See stdout and '
+                'stderr reported above. Command was "%s".  PYTHONPATH was '
+                '"%s".  BRZ_PLUGIN_PATH was "%s".' %
                 (' '.join(command),
                  env.get('PYTHONPATH'),
-                 env.get('BZR_PLUGIN_PATH')))
+                 env.get('BRZ_PLUGIN_PATH')))
 
     def tearDown(self):
         # SIGTERM is the graceful exit request, potentially we could wait a
@@ -234,8 +234,8 @@ class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
         """
         return self.run_bzr_subprocess(
             args, env_changes={
-                'BZR_SSH': 'paramiko',
-                'BZR_PLUGIN_PATH': get_BZR_PLUGIN_PATH_for_subprocess()
+                'BRZ_SSH': 'paramiko',
+                'BRZ_PLUGIN_PATH': get_BRZ_PLUGIN_PATH_for_subprocess()
             },
             allow_plugins=True, retcode=retcode)
 
@@ -244,7 +244,7 @@ class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
         """
         output, error = self._run_bzr(args, retcode=3)
         for line in error.splitlines():
-            if line.startswith("bzr: ERROR"):
+            if line.startswith("brz: ERROR"):
                 return line
         raise AssertionError(
             "Didn't find error line in output:\n\n%s\n" % error)
@@ -253,12 +253,12 @@ class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
         """Branch from the given URL to a local directory."""
         self._run_bzr(['branch', remote_url, local_directory])
 
-    def get_bzr_path(self):
-        """See `bzrlib.tests.TestCase.get_bzr_path`.
+    def get_brz_path(self):
+        """See `breezy.tests.TestCase.get_brz_path`.
 
-        We override this to return the 'bzr' executable from sourcecode.
+        We override this to return our own 'brz' executable.
         """
-        return get_bzr_path()
+        return get_brz_path()
 
     def push(self, local_directory, remote_url, extra_args=None):
         """Push the local branch to the given URL."""
@@ -271,19 +271,19 @@ class SSHTestCase(TestCaseWithTransport, LoomTestMixin, TestCaseWithFactory):
         """Check that we cannot push from 'local_directory' to 'remote_url'.
 
         In addition, if a list of messages is supplied as the error_messages
-        argument, check that the bzr client printed one of these messages
-        which shouldn't include the 'bzr: ERROR:' part of the message.
+        argument, check that the brz client printed one of these messages
+        which shouldn't include the 'brz: ERROR:' part of the message.
 
         :return: The last line of the stderr from the subprocess, which will
-            be the 'bzr: ERROR: <repr of Exception>' line.
+            be the 'brz: ERROR: <repr of Exception>' line.
         """
         error_line = self._run_bzr_error(
             ['push', '-d', local_directory, remote_url])
-        # This will be the will be the 'bzr: ERROR: <repr of Exception>' line.
+        # This will be the 'brz: ERROR: <repr of Exception>' line.
         if not error_messages:
             return error_line
         for msg in error_messages:
-            if error_line.startswith('bzr: ERROR: ' + msg):
+            if error_line.startswith('brz: ERROR: ' + msg):
                 return error_line
         self.fail(
             "Error message %r didn't match any of those supplied."
@@ -340,11 +340,11 @@ class SmokeTest(WithScenarios, SSHTestCase):
     """Smoke test for repository support."""
 
     excluded_scenarios = [
-        # RepositoryFormat4 is not initializable (bzrlib raises TestSkipped
+        # RepositoryFormat4 is not initializable (breezy raises TestSkipped
         # when you try).
         'RepositoryFormat4',
         # Fetching weave formats from the smart server is known to be broken.
-        # See bug 173807 and bzrlib.tests.test_repository.
+        # See bug 173807 and breezy.tests.test_repository.
         'RepositoryFormat5',
         'RepositoryFormat6',
         'RepositoryFormat7',
@@ -364,14 +364,14 @@ class SmokeTest(WithScenarios, SSHTestCase):
         self.second_tree = 'second'
 
     def make_branch_specifying_repo_format(self, relpath, repo_format):
-        bd = self.make_bzrdir(relpath, format=self.bzrdir_format)
+        bd = self.make_controldir(relpath, format=self.bzrdir_format)
         repo_format.initialize(bd)
         return bd.create_branch()
 
     def make_branch_and_tree(self, relpath):
         b = self.make_branch_specifying_repo_format(
             relpath, self.repository_format)
-        return b.bzrdir.create_workingtree()
+        return b.controldir.create_workingtree()
 
     def test_smoke(self):
         # Make a new branch
@@ -411,7 +411,7 @@ class AcceptanceTests(WithScenarios, SSHTestCase):
         error_line = self._run_bzr_error(
             ['cat-revision', '-r', 'branch:' + url])
         self.assertTrue(
-            error_line.startswith('bzr: ERROR: Not a branch:'),
+            error_line.startswith('brz: ERROR: Not a branch:'),
             'Expected "Not a branch", found %r' % error_line)
 
     def makeDatabaseBranch(self, owner_name, product_name, branch_name,
@@ -693,7 +693,7 @@ class SmartserverTests(WithScenarios, SSHTestCase):
         # We can get information from a read-only branch.
         ro_branch_url = self.createBazaarBranch(
             'mark', '+junk', 'ro-branch')
-        revision = bzrlib.branch.Branch.open(ro_branch_url).last_revision()
+        revision = breezy.branch.Branch.open(ro_branch_url).last_revision()
         remote_revision = self.getLastRevision(
             self.getTransportURL('~mark/+junk/ro-branch'))
         self.assertEqual(revision, remote_revision)
@@ -715,7 +715,7 @@ class SmartserverTests(WithScenarios, SSHTestCase):
         # Added to catch bug 126245.
         ro_branch_url = self.makeMirroredBranch(
             'testuser', 'firefox', 'mirror')
-        revision = bzrlib.branch.Branch.open(ro_branch_url).last_revision()
+        revision = breezy.branch.Branch.open(ro_branch_url).last_revision()
         remote_revision = self.getLastRevision(
             self.getTransportURL('~testuser/firefox/mirror'))
         self.assertEqual(revision, remote_revision)
@@ -724,7 +724,7 @@ class SmartserverTests(WithScenarios, SSHTestCase):
         # Users should be able to read mirrored branches even if they don't
         # own those branches.
         ro_branch_url = self.makeMirroredBranch('mark', 'firefox', 'mirror')
-        revision = bzrlib.branch.Branch.open(ro_branch_url).last_revision()
+        revision = breezy.branch.Branch.open(ro_branch_url).last_revision()
         remote_revision = self.getLastRevision(
             self.getTransportURL('~mark/firefox/mirror'))
         self.assertEqual(revision, remote_revision)
diff --git a/lib/lp/codehosting/tests/test_bzrlib.py b/lib/lp/codehosting/tests/test_breezy.py
similarity index 58%
rename from lib/lp/codehosting/tests/test_bzrlib.py
rename to lib/lp/codehosting/tests/test_breezy.py
index 35f44aa..c9cf83d 100644
--- a/lib/lp/codehosting/tests/test_bzrlib.py
+++ b/lib/lp/codehosting/tests/test_breezy.py
@@ -1,17 +1,17 @@
 # Copyright 2009 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""Launchpad specific tests of bzrlib behaviour."""
+"""Launchpad-specific tests of Breezy behaviour."""
 
 __metaclass__ = type
 
 from lp.testing import TestCase
 
 
-class TestBzrlib(TestCase):
+class TestBreezy(TestCase):
     def test_has_cextensions(self):
-        """Ensure Bazaar C extensions are being used."""
+        """Ensure Breezy C extensions are being used."""
         try:
-            import bzrlib._dirstate_helpers_pyx
+            import breezy.bzr._dirstate_helpers_pyx
         except ImportError:
-            self.fail("Bzr not built with C extensions.")
+            self.fail("Breezy not built with C extensions.")
diff --git a/lib/lp/codehosting/tests/test_bzrutils.py b/lib/lp/codehosting/tests/test_bzrutils.py
index e05c14d..a78d35f 100644
--- a/lib/lp/codehosting/tests/test_bzrutils.py
+++ b/lib/lp/codehosting/tests/test_bzrutils.py
@@ -8,20 +8,23 @@ __metaclass__ = type
 import gc
 import sys
 
-from bzrlib import (
+from breezy import (
     errors,
     trace,
     )
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import format_registry
-from bzrlib.errors import AppendRevisionsOnlyViolation
-from bzrlib.remote import RemoteBranch
-from bzrlib.tests import (
+from breezy.branch import (
+    Branch,
+    UnstackableBranchFormat,
+    )
+from breezy.bzr.remote import RemoteBranch
+from breezy.controldir import format_registry
+from breezy.errors import AppendRevisionsOnlyViolation
+from breezy.tests import (
     test_server,
     TestCaseWithTransport,
     TestNotApplicable,
     )
-from bzrlib.tests.per_branch import (
+from breezy.tests.per_branch import (
     branch_scenarios,
     TestCaseWithControlDir,
     )
@@ -80,14 +83,14 @@ class TestGetBranchStackedOnURL(WithScenarios, TestCaseWithControlDir):
         stacked_branch = self.make_branch('stacked')
         try:
             stacked_branch.set_stacked_on_url('../stacked-on')
-        except errors.UnstackableBranchFormat:
+        except UnstackableBranchFormat:
             raise TestNotApplicable('This format does not support stacking.')
         # Deleting the stacked-on branch ensures that Bazaar will raise an
         # error if it tries to open the stacked-on branch.
         self.get_transport('.').delete_tree('stacked-on')
         self.assertEqual(
             '../stacked-on',
-            get_branch_stacked_on_url(stacked_branch.bzrdir))
+            get_branch_stacked_on_url(stacked_branch.controldir))
 
     def testGetBranchStackedOnUrlUnstackable(self):
         # get_branch_stacked_on_url raises UnstackableBranchFormat if it's
@@ -97,11 +100,11 @@ class TestGetBranchStackedOnURL(WithScenarios, TestCaseWithControlDir):
             branch.get_stacked_on_url()
         except errors.NotStacked:
             raise TestNotApplicable('This format supports stacked branches.')
-        except errors.UnstackableBranchFormat:
+        except UnstackableBranchFormat:
             pass
         self.assertRaises(
-            errors.UnstackableBranchFormat,
-            get_branch_stacked_on_url, branch.bzrdir)
+            UnstackableBranchFormat,
+            get_branch_stacked_on_url, branch.controldir)
 
     def testGetBranchStackedOnUrlNotStacked(self):
         # get_branch_stacked_on_url raises NotStacked if it's called on the
@@ -111,16 +114,16 @@ class TestGetBranchStackedOnURL(WithScenarios, TestCaseWithControlDir):
             branch.get_stacked_on_url()
         except errors.NotStacked:
             pass
-        except errors.UnstackableBranchFormat:
+        except UnstackableBranchFormat:
             raise TestNotApplicable(
                 'This format does not support stacked branches')
         self.assertRaises(
-            errors.NotStacked, get_branch_stacked_on_url, branch.bzrdir)
+            errors.NotStacked, get_branch_stacked_on_url, branch.controldir)
 
     def testGetBranchStackedOnUrlNoBranch(self):
         # get_branch_stacked_on_url raises a NotBranchError if it's called on
         # a bzrdir that's not got a branch.
-        a_bzrdir = self.make_bzrdir('source')
+        a_bzrdir = self.make_controldir('source')
         if a_bzrdir.has_branch():
             raise TestNotApplicable(
                 'This format does not support branchless bzrdirs.')
diff --git a/lib/lp/codehosting/tests/test_format_comparison.py b/lib/lp/codehosting/tests/test_format_comparison.py
index 0346af7..de06e64 100644
--- a/lib/lp/codehosting/tests/test_format_comparison.py
+++ b/lib/lp/codehosting/tests/test_format_comparison.py
@@ -45,7 +45,7 @@ class StubObjectWithFormat:
 class StubBranch:
     """A stub branch object that just has formats."""
     def __init__(self, bzrdir_format, repo_format, branch_format):
-        self.bzrdir = StubObjectWithFormat(bzrdir_format)
+        self.controldir = StubObjectWithFormat(bzrdir_format)
         self.repository = StubObjectWithFormat(repo_format)
         self._format = branch_format
 
diff --git a/lib/lp/codehosting/tests/test_lpserve.py b/lib/lp/codehosting/tests/test_lpserve.py
index 2655e7e..81294cc 100644
--- a/lib/lp/codehosting/tests/test_lpserve.py
+++ b/lib/lp/codehosting/tests/test_lpserve.py
@@ -5,10 +5,10 @@
 
 __metaclass__ = type
 
-from bzrlib import errors
-from bzrlib.plugins.lpserve.test_lpserve import TestCaseWithSubprocess
-from bzrlib.smart import medium
-from bzrlib.transport import remote
+from breezy import errors
+from breezy.bzr.smart import medium
+from breezy.plugins.lpserve.test_lpserve import TestCaseWithSubprocess
+from breezy.transport import remote
 
 from lp.testing.fixture import CaptureOops
 from lp.testing.layers import LaunchpadLayer
@@ -112,8 +112,8 @@ class TestLaunchpadServe(TestCaseWithSubprocess):
 
 
 def test_suite():
-    from bzrlib import tests
-    from bzrlib.plugins import lpserve
+    from breezy import tests
+    from breezy.plugins import lpserve
 
     loader = tests.TestLoader()
     suite = loader.loadTestsFromName(__name__)
diff --git a/lib/lp/codehosting/tests/test_sftp.py b/lib/lp/codehosting/tests/test_sftp.py
index 7539dd6..3ea1309 100644
--- a/lib/lp/codehosting/tests/test_sftp.py
+++ b/lib/lp/codehosting/tests/test_sftp.py
@@ -6,13 +6,13 @@
 from contextlib import closing
 import os
 
-from bzrlib import (
+from breezy import (
     errors as bzr_errors,
     urlutils,
     )
-from bzrlib.tests import TestCaseInTempDir
-from bzrlib.transport import get_transport
-from bzrlib.transport.memory import MemoryTransport
+from breezy.tests import TestCaseInTempDir
+from breezy.transport import get_transport
+from breezy.transport.memory import MemoryTransport
 from lazr.sshserver.sftp import FileIsADirectory
 from testtools.twistedsupport import (
     assert_fails_with,
@@ -70,7 +70,7 @@ class TestFatLocalTransport(TestCaseInTempDir):
     def test_writeChunk(self):
         # writeChunk writes a chunk of data to a file at a given offset.
         filename = 'foo'
-        self.transport.put_bytes(filename, 'content')
+        self.transport.put_bytes(filename, b'content')
         self.transport.writeChunk(filename, 1, 'razy')
         self.assertEqual('crazynt', self.transport.get_bytes(filename))
 
@@ -612,7 +612,7 @@ class TestSFTPServer(TestCaseInTempDir, SFTPTestMixin):
     def test_openDirectoryMemory(self):
         """openDirectory works on MemoryTransport."""
         transport = MemoryTransport()
-        transport.put_bytes('hello', 'hello')
+        transport.put_bytes('hello', b'hello')
         sftp_server = TransportSFTPServer(AsyncTransport(transport))
         deferred = sftp_server.openDirectory('.')
 
diff --git a/lib/lp/codehosting/tests/test_upgrade.py b/lib/lp/codehosting/tests/test_upgrade.py
index 8d53d28..3326d16 100644
--- a/lib/lp/codehosting/tests/test_upgrade.py
+++ b/lib/lp/codehosting/tests/test_upgrade.py
@@ -7,18 +7,16 @@ __metaclass__ = type
 import logging
 from os.path import dirname
 
-from bzrlib.branch import Branch
-from bzrlib.bzrdir import (
-    BzrDir,
-    format_registry,
-    )
-from bzrlib.plugins.loom.branch import loomify
-from bzrlib.repofmt.groupcompress_repo import (
+from breezy.branch import Branch
+from breezy.bzr.bzrdir import BzrDir
+from breezy.bzr.groupcompress_repo import (
     RepositoryFormat2a,
     RepositoryFormat2aSubtree,
     )
-from bzrlib.revision import NULL_REVISION
-from bzrlib.transport import get_transport
+from breezy.controldir import format_registry
+from breezy.plugins.loom.branch import loomify
+from breezy.revision import NULL_REVISION
+from breezy.transport import get_transport
 from fixtures import TempDir
 
 from lp.code.bzr import (
@@ -51,7 +49,7 @@ class TestUpgrader(TestCaseWithFactory):
             'foo', rev_id='prepare-commit', committer='jrandom@xxxxxxxxxxx')
         if loomify_branch:
             loomify(tree.branch)
-            bzr_branch = tree.bzrdir.open_branch()
+            bzr_branch = tree.controldir.open_branch()
         else:
             bzr_branch = tree.branch
         return self.getUpgrader(bzr_branch, branch)
@@ -76,8 +74,8 @@ class TestUpgrader(TestCaseWithFactory):
         :param tree: A Bazaar WorkingTree to add a tree to.
         """
         sub_branch = BzrDir.create_branch_convenience(
-            tree.bzrdir.root_transport.clone('sub').base)
-        tree.add_reference(sub_branch.bzrdir.open_workingtree())
+            tree.controldir.root_transport.clone('sub').base)
+        tree.add_reference(sub_branch.controldir.open_workingtree())
         tree.commit('added tree reference', committer='jrandom@xxxxxxxxxxx')
 
     def check_branch(self, upgraded, branch_format=BranchFormat.BZR_BRANCH_7,
@@ -128,7 +126,7 @@ class TestUpgrader(TestCaseWithFactory):
     def test_subtree_format_repo_format(self):
         """Even subtree formats use 2a if they don't have tree references."""
         self.useBzrBranches(direct_database=True)
-        format = format_registry.make_bzrdir('pack-0.92-subtree')
+        format = format_registry.make_controldir('pack-0.92-subtree')
         branch, tree = self.create_branch_and_tree(format=format)
         upgrader = self.getUpgrader(tree.branch, branch)
         with read_locked(upgrader.bzr_branch):
@@ -139,7 +137,7 @@ class TestUpgrader(TestCaseWithFactory):
     def test_tree_reference_repo_format(self):
         """Repos with tree references get 2aSubtree."""
         self.useBzrBranches(direct_database=True)
-        format = format_registry.make_bzrdir('pack-0.92-subtree')
+        format = format_registry.make_controldir('pack-0.92-subtree')
         branch, tree = self.create_branch_and_tree(format=format)
         upgrader = self.getUpgrader(tree.branch, branch)
         self.addTreeReference(tree)
@@ -186,7 +184,7 @@ class TestUpgrader(TestCaseWithFactory):
     def test_has_tree_references(self):
         """Detects whether repo contains actual tree references."""
         self.useBzrBranches(direct_database=True)
-        format = format_registry.make_bzrdir('pack-0.92-subtree')
+        format = format_registry.make_controldir('pack-0.92-subtree')
         branch, tree = self.create_branch_and_tree(format=format)
         upgrader = self.getUpgrader(tree.branch, branch)
         with read_locked(tree.branch.repository):
@@ -198,11 +196,11 @@ class TestUpgrader(TestCaseWithFactory):
     def test_use_subtree_format_for_tree_references(self):
         """Subtree references cause RepositoryFormat2aSubtree to be used."""
         self.useBzrBranches(direct_database=True)
-        format = format_registry.make_bzrdir('pack-0.92-subtree')
+        format = format_registry.make_controldir('pack-0.92-subtree')
         branch, tree = self.create_branch_and_tree(format=format)
         sub_branch = BzrDir.create_branch_convenience(
-            tree.bzrdir.root_transport.clone('sub').base, format=format)
-        tree.add_reference(sub_branch.bzrdir.open_workingtree())
+            tree.controldir.root_transport.clone('sub').base, format=format)
+        tree.add_reference(sub_branch.controldir.open_workingtree())
         tree.commit('added tree reference', committer='jrandom@xxxxxxxxxxx')
         upgrader = self.getUpgrader(tree.branch, branch)
         with read_locked(tree.branch):
diff --git a/lib/lp/codehosting/upgrade.py b/lib/lp/codehosting/upgrade.py
index 43e592f..2159871 100755
--- a/lib/lp/codehosting/upgrade.py
+++ b/lib/lp/codehosting/upgrade.py
@@ -18,18 +18,16 @@ import os
 from shutil import rmtree
 from tempfile import mkdtemp
 
-from bzrlib.bzrdir import (
-    BzrDir,
-    format_registry,
-    )
-from bzrlib.errors import UpToDateFormat
-from bzrlib.plugins.loom import (
+from breezy.bzr.bzrdir import BzrDir
+from breezy.bzr.groupcompress_repo import RepositoryFormat2aSubtree
+from breezy.controldir import format_registry
+from breezy.errors import UpToDateFormat
+from breezy.plugins.loom import (
     NotALoom,
     require_loom_branch,
     )
-from bzrlib.repofmt.groupcompress_repo import RepositoryFormat2aSubtree
-from bzrlib.upgrade import upgrade
-from bzrlib.url_policy_open import (
+from breezy.upgrade import upgrade
+from breezy.url_policy_open import (
     BranchOpener,
     SingleSchemePolicy,
     )
@@ -75,7 +73,7 @@ class Upgrader:
         :param branch: The bzr branch to upgrade
         :return: A Metadir format instance.
         """
-        format = format_registry.make_bzrdir('2a')
+        format = format_registry.make_controldir('2a')
         try:
             require_loom_branch(self.bzr_branch)
         except NotALoom:
@@ -205,5 +203,5 @@ class Upgrader:
     def mirror_branch(self, bzr_branch, target_bd):
         """Mirror the actual branch from a bzr_branch to a target bzrdir."""
         target = target_bd.get_branch_transport(bzr_branch._format)
-        source = bzr_branch.bzrdir.get_branch_transport(bzr_branch._format)
+        source = bzr_branch.controldir.get_branch_transport(bzr_branch._format)
         source.copy_tree_to_transport(target)
diff --git a/lib/lp/codehosting/vfs/branchfs.py b/lib/lp/codehosting/vfs/branchfs.py
index a928855..92d4b3f 100644
--- a/lib/lp/codehosting/vfs/branchfs.py
+++ b/lib/lp/codehosting/vfs/branchfs.py
@@ -29,7 +29,7 @@ the `IBranchFileSystem` interface and passing what that returns to a
 `ITransportDispatch` object.
 
 We hook the `LaunchpadServer` into Bazaar by implementing a
-`AsyncVirtualTransport`, a `bzrlib.transport.Transport` that wraps all of its
+`AsyncVirtualTransport`, a `breezy.transport.Transport` that wraps all of its
 operations so that they are translated by an object that implements
 `translateVirtualPath`.  See transport.py for more information.
 
@@ -58,20 +58,18 @@ import os.path
 import sys
 import xmlrpclib
 
-from bzrlib import urlutils
-from bzrlib.bzrdir import (
-    BzrDir,
-    BzrDirFormat,
-    )
-from bzrlib.config import TransportConfig
-from bzrlib.errors import (
+from breezy import urlutils
+from breezy.bzr.bzrdir import BzrDir
+from breezy.bzr.smart.request import jail_info
+from breezy.config import TransportConfig
+from breezy.controldir import ControlDirFormat
+from breezy.errors import (
     NoSuchFile,
     PermissionDenied,
     TransportNotPossible,
     )
-from bzrlib.smart.request import jail_info
-from bzrlib.transport import get_transport
-from bzrlib.transport.memory import MemoryServer
+from breezy.transport import get_transport
+from breezy.transport.memory import MemoryServer
 from lazr.uri import URI
 import six
 from twisted.internet import (
@@ -224,7 +222,7 @@ class ITransportDispatch(Interface):
 
         :return: A transport and a path on that transport that point to a
             place that matches the one described in transport_tuple.
-        :rtype: (`bzrlib.transport.Transport`, str)
+        :rtype: (`breezy.transport.Transport`, str)
         """
 
 
@@ -333,7 +331,7 @@ class TransportDispatch:
         transport = get_transport(memory_server.get_url())
         if default_stack_on == '':
             return transport
-        format = BzrDirFormat.get_default_format()
+        format = ControlDirFormat.get_default_format()
         bzrdir = format.initialize_on_transport(transport)
         bzrdir.get_config().set_default_stack_on(
             urlutils.unescape(default_stack_on))
diff --git a/lib/lp/codehosting/vfs/tests/test_branchfs.py b/lib/lp/codehosting/vfs/tests/test_branchfs.py
index 30c08d4..eba8732 100644
--- a/lib/lp/codehosting/vfs/tests/test_branchfs.py
+++ b/lib/lp/codehosting/vfs/tests/test_branchfs.py
@@ -12,29 +12,27 @@ from StringIO import StringIO
 import sys
 import xmlrpclib
 
-from bzrlib import errors
-from bzrlib.bzrdir import (
-    BzrDir,
-    format_registry,
-    )
-from bzrlib.tests import (
+from breezy import errors
+from breezy.bzr.bzrdir import BzrDir
+from breezy.controldir import format_registry
+from breezy.tests import (
     TestCase as BzrTestCase,
     TestCaseInTempDir,
     TestCaseWithTransport,
     )
-from bzrlib.transport import (
+from breezy.transport import (
     _get_protocol_handlers,
     get_transport,
     register_transport,
     Server,
     unregister_transport,
     )
-from bzrlib.transport.chroot import ChrootTransport
-from bzrlib.transport.memory import (
+from breezy.transport.chroot import ChrootTransport
+from breezy.transport.memory import (
     MemoryServer,
     MemoryTransport,
     )
-from bzrlib.urlutils import (
+from breezy.urlutils import (
     escape,
     local_path_to_url,
     )
@@ -142,7 +140,7 @@ class TestTransportDispatch(TestCase):
             default_stack_on='/~foo/bar/baz')
         self.assertRaises(
             errors.TransportNotPossible,
-            transport.put_bytes, '.bzr/control.conf', 'data')
+            transport.put_bytes, '.bzr/control.conf', b'data')
 
     def test_control_conf_with_stacking(self):
         transport = self.factory._makeControlTransport(
@@ -159,7 +157,7 @@ class TestTransportDispatch(TestCase):
         transport = self.factory._makeBranchTransport(id=5, writable=False)
         self.assertRaises(
             errors.TransportNotPossible, transport.put_bytes,
-            '.bzr/README', 'data')
+            '.bzr/README', b'data')
 
     def test_writable_implies_writable(self):
         transport = self.factory._makeBranchTransport(id=5, writable=True)
@@ -559,7 +557,7 @@ class LaunchpadTransportTests:
             transport.put_bytes,
             '~%s/%s/.bzr/control.conf' % (
                 branch.owner.name, branch.product.name),
-            'hello nurse!')
+            b'hello nurse!')
 
     def _makeOnBackingTransport(self, branch):
         """Make directories for 'branch' on the backing transport.
@@ -578,7 +576,7 @@ class LaunchpadTransportTests:
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=self.requester)
         backing_transport = self._makeOnBackingTransport(branch)
-        backing_transport.put_bytes('hello.txt', 'Hello World!')
+        backing_transport.put_bytes('hello.txt', b'Hello World!')
         deferred = self._ensureDeferred(
             transport.get_bytes, '%s/.bzr/hello.txt' % branch.unique_name)
         return deferred.addCallback(self.assertEqual, 'Hello World!')
@@ -589,7 +587,7 @@ class LaunchpadTransportTests:
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=self.requester)
         backing_transport = self._makeOnBackingTransport(branch)
-        backing_transport.put_bytes('hello.txt', 'Hello World!')
+        backing_transport.put_bytes('hello.txt', b'Hello World!')
         url = escape('%s/.bzr/hello.txt' % branch.unique_name)
         transport = self.getTransport()
         deferred = self._ensureDeferred(transport.get_bytes, url)
@@ -601,7 +599,7 @@ class LaunchpadTransportTests:
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=self.requester)
         backing_transport = self._makeOnBackingTransport(branch)
-        data = 'Hello World!'
+        data = b'Hello World!'
         backing_transport.put_bytes('hello.txt', data)
         transport = self.getTransport()
         deferred = self._ensureDeferred(
@@ -622,7 +620,7 @@ class LaunchpadTransportTests:
         backing_transport = self._makeOnBackingTransport(branch)
         deferred = self._ensureDeferred(
             transport.put_bytes,
-            '%s/.bzr/goodbye.txt' % branch.unique_name, "Goodbye")
+            '%s/.bzr/goodbye.txt' % branch.unique_name, b"Goodbye")
 
         def check_bytes_written(ignored):
             self.assertEqual(
@@ -659,7 +657,7 @@ class LaunchpadTransportTests:
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=self.requester)
         backing_transport = self._makeOnBackingTransport(branch)
-        backing_transport.put_bytes('hello.txt', 'Hello World!')
+        backing_transport.put_bytes('hello.txt', b'Hello World!')
         transport = transport.clone('~%s' % branch.owner.name)
         deferred = self._ensureDeferred(
             transport.get_bytes,
@@ -696,7 +694,7 @@ class LaunchpadTransportTests:
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=self.requester)
         backing_transport = self._makeOnBackingTransport(branch)
-        backing_transport.put_bytes('hello.txt', 'Hello World!')
+        backing_transport.put_bytes('hello.txt', b'Hello World!')
 
         transport = self.getTransport().clone(branch.unique_name)
 
@@ -735,7 +733,7 @@ class LaunchpadTransportTests:
         branch = self.factory.makeAnyBranch(
             branch_type=BranchType.HOSTED, owner=self.requester)
         backing_transport = self._makeOnBackingTransport(branch)
-        backing_transport.put_bytes('hello.txt', 'Hello World!')
+        backing_transport.put_bytes('hello.txt', b'Hello World!')
         transport = self.getTransport().clone(branch.unique_name)
         backing_transport = self.backing_transport.clone(
             branch_to_path(branch))
@@ -985,7 +983,7 @@ class TestBranchChangedNotification(TestCaseWithTransport):
 
     def assertFormatStringsPassed(self, branch):
         self.assertEqual(1, len(self._branch_changed_log))
-        control_string = branch.bzrdir._format.get_format_string()
+        control_string = branch.controldir._format.get_format_string()
         branch_string = branch._format.get_format_string()
         repository_string = branch.repository._format.get_format_string()
         self.assertEqual(
@@ -1130,7 +1128,7 @@ class TestLaunchpadTransportReadOnly(BzrTestCase):
             self.requester.id, codehosting_api, backing_transport)
         self.lp_transport = get_transport(self.lp_server.get_url())
         self.lp_transport.mkdir(os.path.dirname(self.writable_file))
-        self.lp_transport.put_bytes(self.writable_file, 'Hello World!')
+        self.lp_transport.put_bytes(self.writable_file, b'Hello World!')
 
     def _setUpMemoryServer(self):
         memory_server = MemoryServer()
diff --git a/lib/lp/codehosting/vfs/tests/test_filesystem.py b/lib/lp/codehosting/vfs/tests/test_filesystem.py
index 467ec2a..3e03e94 100644
--- a/lib/lp/codehosting/vfs/tests/test_filesystem.py
+++ b/lib/lp/codehosting/vfs/tests/test_filesystem.py
@@ -7,12 +7,12 @@ __metaclass__ = type
 
 import stat
 
-from bzrlib import errors
-from bzrlib.bzrdir import BzrDir
-from bzrlib.tests import TestCaseWithTransport
-from bzrlib.transport import get_transport
-from bzrlib.transport.memory import MemoryTransport
-from bzrlib.urlutils import escape
+from breezy import errors
+from breezy.bzr.bzrdir import BzrDir
+from breezy.tests import TestCaseWithTransport
+from breezy.transport import get_transport
+from breezy.transport.memory import MemoryTransport
+from breezy.urlutils import escape
 
 from lp.code.interfaces.branchtarget import IBranchTarget
 from lp.code.interfaces.codehosting import branch_id_alias
@@ -218,7 +218,7 @@ class TestFilesystem(TestCaseWithTransport):
         transport.mkdir(branch_path)
         self.assertRaises(
             errors.PermissionDenied,
-            transport.put_bytes, '%s/README' % branch_path, 'Hello!')
+            transport.put_bytes, '%s/README' % branch_path, b'Hello!')
 
     def test_rename_to_non_bzr_directory_fails(self):
         # Users cannot create an allowed directory (e.g. '.bzr' or
@@ -296,7 +296,7 @@ class TestFilesystem(TestCaseWithTransport):
         # unescape(path).encode('utf-8') != path.
         path = '%41%42%43'
         escaped_path = escape(path)
-        content = 'content'
+        content = b'content'
         transport.put_bytes(escaped_path, content)
 
         # We can use the escaped path to reach the file.
diff --git a/lib/lp/codehosting/vfs/tests/test_transport.py b/lib/lp/codehosting/vfs/tests/test_transport.py
index e4bc291..45c155a 100644
--- a/lib/lp/codehosting/vfs/tests/test_transport.py
+++ b/lib/lp/codehosting/vfs/tests/test_transport.py
@@ -5,14 +5,14 @@
 
 __metaclass__ = type
 
-from bzrlib.tests import per_transport
-from bzrlib.transport import (
+from breezy.tests import per_transport
+from breezy.transport import (
     chroot,
     get_transport,
     Transport,
     )
-from bzrlib.transport.local import LocalTransport
-from bzrlib.urlutils import local_path_to_url
+from breezy.transport.local import LocalTransport
+from breezy.urlutils import local_path_to_url
 
 from lp.codehosting.inmemory import InMemoryFrontend
 from lp.codehosting.tests.helpers import TestResultWrapper
diff --git a/lib/lp/codehosting/vfs/tests/test_transport_extensions.py b/lib/lp/codehosting/vfs/tests/test_transport_extensions.py
index 31c07a1..56b587f 100644
--- a/lib/lp/codehosting/vfs/tests/test_transport_extensions.py
+++ b/lib/lp/codehosting/vfs/tests/test_transport_extensions.py
@@ -5,7 +5,7 @@
 
 __metaclass__ = type
 
-from bzrlib.transport.memory import MemoryTransport
+from breezy.transport.memory import MemoryTransport
 
 from lp.codehosting.vfs.transport import get_readonly_transport
 from lp.testing import TestCase
diff --git a/lib/lp/codehosting/vfs/transport.py b/lib/lp/codehosting/vfs/transport.py
index db67847..f53b49a 100644
--- a/lib/lp/codehosting/vfs/transport.py
+++ b/lib/lp/codehosting/vfs/transport.py
@@ -5,7 +5,7 @@
 
 The code hosting filesystem is implemented using Bazaar transports. This
 module contains utilities for implementing virtual filesystems using
-bzrlib.transport classes.
+breezy.transport classes.
 """
 
 __metaclass__ = type
@@ -19,14 +19,14 @@ __all__ = [
     ]
 
 
-from bzrlib import urlutils
-from bzrlib.errors import (
+from breezy import urlutils
+from breezy.errors import (
     BzrError,
     InProcessTransport,
     NoSuchFile,
     TransportNotPossible,
     )
-from bzrlib.transport import (
+from breezy.transport import (
     chroot,
     get_transport,
     register_transport,
@@ -113,7 +113,7 @@ class AsyncVirtualTransport(Transport):
         This method is called as an errback by `_call`. Use it to translate
         errors from the server into something that users of the transport
         might expect. This could include translating vfs-specific errors into
-        bzrlib errors (e.g. "couldn\'t translate" into `NoSuchFile`) or
+        breezy errors (e.g. "couldn\'t translate" into `NoSuchFile`) or
         translating underlying paths into virtual paths.
 
         :param failure: A `twisted.python.failure.Failure`.
@@ -276,105 +276,105 @@ class SynchronousAdapter(Transport):
         return self._async_transport.set_segment_parameter(name, value)
 
     def clone(self, offset=None):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         cloned_async = self._async_transport.clone(offset)
         return SynchronousAdapter(cloned_async)
 
     def external_url(self):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         raise InProcessTransport(self)
 
     def abspath(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return self._async_transport.abspath(relpath)
 
     def append_file(self, relpath, f, mode=None):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(
             self._async_transport.append_file(relpath, f, mode))
 
     def delete(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.delete(relpath))
 
     def delete_tree(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.delete_tree(relpath))
 
     def get(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.get(relpath))
 
     def get_bytes(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.get_bytes(relpath))
 
     def has(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.has(relpath))
 
     def iter_files_recursive(self):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(
             self._async_transport.iter_files_recursive())
 
     def listable(self):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.listable())
 
     def list_dir(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.list_dir(relpath))
 
     def lock_read(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.lock_read(relpath))
 
     def lock_write(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.lock_write(relpath))
 
     def mkdir(self, relpath, mode=None):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.mkdir(relpath, mode))
 
     def open_write_stream(self, relpath, mode=None):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(
             self._async_transport.open_write_stream(relpath, mode))
 
     def put_file(self, relpath, f, mode=None):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(
             self._async_transport.put_file(relpath, f, mode))
 
     def local_realPath(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `lp.codehosting.sftp.FatLocalTransport`."""
         return extract_result(
             self._async_transport.local_realPath(relpath))
 
     def readv(self, relpath, offsets, adjust_for_latency=False,
               upper_limit=None):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(
             self._async_transport.readv(
                 relpath, offsets, adjust_for_latency, upper_limit))
 
     def rename(self, rel_from, rel_to):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(
             self._async_transport.rename(rel_from, rel_to))
 
     def rmdir(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.rmdir(relpath))
 
     def stat(self, relpath):
-        """See `bzrlib.transport.Transport`."""
+        """See `breezy.transport.Transport`."""
         return extract_result(self._async_transport.stat(relpath))
 
     def writeChunk(self, relpath, offset, data):
-        """See `bzrlib.transport.Transport`."""
+        """See `lp.codehosting.sftp.FatLocalTransport`."""
         return extract_result(
             self._async_transport.writeChunk(relpath, offset, data))
 
@@ -394,7 +394,7 @@ class AsyncVirtualServer(Server):
 
         :param scheme: The URL scheme to use.
         """
-        # bzrlib's Server class does not have a constructor, so we cannot
+        # breezy's Server class does not have a constructor, so we cannot
         # safely upcall it.
         self._scheme = scheme
         self._is_started = False
diff --git a/lib/lp/scripts/runlaunchpad.py b/lib/lp/scripts/runlaunchpad.py
index 60332e6..b66e26f 100644
--- a/lib/lp/scripts/runlaunchpad.py
+++ b/lib/lp/scripts/runlaunchpad.py
@@ -202,13 +202,13 @@ class ForkingSessionService(Service):
         # service.
         if not self.should_launch:
             return
-        from lp.codehosting import get_bzr_path
-        command = [config.root + '/bin/py', get_bzr_path(),
+        from lp.codehosting import get_brz_path
+        command = [config.root + '/bin/py', get_brz_path(),
                    'launchpad-forking-service',
                    '--path', config.codehosting.forking_daemon_socket,
                   ]
         env = dict(os.environ)
-        env['BZR_PLUGIN_PATH'] = config.root + '/bzrplugins'
+        env['BRZ_PLUGIN_PATH'] = config.root + '/brzplugins'
         logfile = self.logfile
         if logfile == '-':
             # This process uses a different logging infrastructure from the
@@ -216,7 +216,7 @@ class ForkingSessionService(Service):
             # as the logfile. So we just ignore this setting.
             pass
         else:
-            env['BZR_LOG'] = logfile
+            env['BRZ_LOG'] = logfile
         process = subprocess.Popen(command, env=env, stdin=subprocess.PIPE)
         self.addCleanup(stop_process, process)
         process.stdin.close()
diff --git a/lib/lp/testing/__init__.py b/lib/lp/testing/__init__.py
index 81e0f1f..15c2af1 100644
--- a/lib/lp/testing/__init__.py
+++ b/lib/lp/testing/__init__.py
@@ -81,12 +81,13 @@ import tempfile
 import time
 import unittest
 
-from bzrlib import trace
-from bzrlib.bzrdir import (
-    BzrDir,
+from breezy import trace
+from breezy.controldir import (
+    ControlDir,
     format_registry,
     )
-from bzrlib.transport import get_transport
+from breezy.transport import get_transport
+from bzrlib import trace as bzr_trace
 import fixtures
 from lazr.restful.testing.tales import test_tales
 from lazr.restful.testing.webservice import FakeRequest
@@ -832,11 +833,12 @@ class TestCaseWithFactory(TestCase):
         self._use_bzr_branch_called = False
         # XXX: JonathanLange 2010-12-24 bug=694140: Because of Launchpad's
         # messing with global log state (see
-        # lp.services.scripts.logger), trace._bzr_logger does not
-        # necessarily equal logging.getLogger('bzr'), so we have to explicitly
-        # make it so in order to avoid "No handlers for "bzr" logger'
+        # lp.services.scripts.logger), trace._brz_logger does not
+        # necessarily equal logging.getLogger('brz'), so we have to explicitly
+        # make it so in order to avoid "No handlers for "brz" logger'
         # messages.
-        trace._bzr_logger = logging.getLogger('bzr')
+        trace._brz_logger = logging.getLogger('brz')
+        bzr_trace._bzr_logger = logging.getLogger('bzr')
 
     def getUserBrowser(self, url=None, user=None):
         """Return a Browser logged in as a fresh user, maybe opened at `url`.
@@ -874,8 +876,7 @@ class TestCaseWithFactory(TestCase):
         """
         if format is not None and isinstance(format, basestring):
             format = format_registry.get(format)()
-        return BzrDir.create_branch_convenience(
-            branch_url, format=format)
+        return ControlDir.create_branch_convenience(branch_url, format=format)
 
     def create_branch_and_tree(self, tree_location=None, product=None,
                                db_branch=None, format=None,
@@ -935,6 +936,7 @@ class TestCaseWithFactory(TestCase):
         self.useTempDir()
         # Avoid leaking local user configuration into tests.
         self.useContext(override_environ(
+            BRZ_HOME=os.getcwd(), BRZ_EMAIL=None,
             BZR_HOME=os.getcwd(), BZR_EMAIL=None, EMAIL=None,
             ))
 
@@ -1392,7 +1394,7 @@ def map_branch_contents(branch):
             for entry in entries:
                 file_path, file_name, file_type = entry[:3]
                 if file_type == 'file':
-                    stored_file = tree.get_file_by_path(file_path)
+                    stored_file = tree.get_file(file_path)
                     contents[file_path] = stored_file.read()
     finally:
         tree.unlock()
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 568ddab..7ea8c6d 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -46,8 +46,8 @@ from types import InstanceType
 import uuid
 import warnings
 
-from bzrlib.plugins.builder.recipe import BaseRecipeBranch
-from bzrlib.revision import Revision as BzrRevision
+from breezy.plugins.builder.recipe import BaseRecipeBranch
+from breezy.revision import Revision as BzrRevision
 from cryptography.utils import int_to_bytes
 from lazr.jobrunner.jobrunner import SuspendJobException
 import pytz
@@ -3035,7 +3035,7 @@ class BareLaunchpadObjectFactory(ObjectFactory):
         If no branches are passed, return a recipe text that references an
         arbitrary branch.
         """
-        from bzrlib.plugins.builder.recipe import RecipeParser
+        from breezy.plugins.builder.recipe import RecipeParser
         parser = RecipeParser(self.makeRecipeText(*branches))
         return parser.parse()
 
diff --git a/lib/lp/translations/browser/productseries.py b/lib/lp/translations/browser/productseries.py
index a5a6588..499e515 100644
--- a/lib/lp/translations/browser/productseries.py
+++ b/lib/lp/translations/browser/productseries.py
@@ -18,7 +18,7 @@ __all__ = [
 
 import os.path
 
-from bzrlib.revision import NULL_REVISION
+from breezy.revision import NULL_REVISION
 from zope.component import getUtility
 from zope.publisher.browser import FileUpload
 
diff --git a/lib/lp/translations/pottery/detect_intltool.py b/lib/lp/translations/pottery/detect_intltool.py
index ae7d8e3..81eb352 100644
--- a/lib/lp/translations/pottery/detect_intltool.py
+++ b/lib/lp/translations/pottery/detect_intltool.py
@@ -26,7 +26,7 @@ def is_intltool_structure(tree):
 
     Currently this just checks for the existence of POTFILES.in.
 
-    :param tree: A bzrlib.Tree object to search for the intltool structure.
+    :param tree: A breezy.Tree object to search for the intltool structure.
     :returns: True if signs of an intltool structure were found.
     """
     with read_lock_tree(tree):
diff --git a/lib/lp/translations/pottery/tests/test_detect_intltool.py b/lib/lp/translations/pottery/tests/test_detect_intltool.py
index 152fb8a..cc0d5d7 100644
--- a/lib/lp/translations/pottery/tests/test_detect_intltool.py
+++ b/lib/lp/translations/pottery/tests/test_detect_intltool.py
@@ -7,7 +7,7 @@ import errno
 import os
 import tarfile
 
-from bzrlib.bzrdir import BzrDir
+from breezy.controldir import ControlDir
 
 from lp.testing import TestCase
 from lp.translations.pottery.detect_intltool import is_intltool_structure
@@ -56,7 +56,7 @@ class SetupTestPackageMixin:
 class TestDetectIntltoolInBzrTree(TestCase, SetupTestPackageMixin):
 
     def prepare_tree(self):
-        return BzrDir.create_standalone_workingtree(".")
+        return ControlDir.create_standalone_workingtree(".")
 
     def test_detect_intltool_structure(self):
         # Detect a simple intltool structure.
diff --git a/lib/lp/translations/scripts/tests/test_translations_to_branch.py b/lib/lp/translations/scripts/tests/test_translations_to_branch.py
index ec201fe..248b2e0 100644
--- a/lib/lp/translations/scripts/tests/test_translations_to_branch.py
+++ b/lib/lp/translations/scripts/tests/test_translations_to_branch.py
@@ -7,7 +7,7 @@ import datetime
 import re
 from textwrap import dedent
 
-from bzrlib.errors import NotBranchError
+from breezy.errors import NotBranchError
 import pytz
 from testtools.matchers import MatchesRegex
 import transaction
@@ -193,7 +193,7 @@ class TestExportTranslationsToBranch(TestCaseWithFactory):
         self.assertTrue("GruesomeException" in message)
 
     def test_exportToBranches_handles_unpushed_branches(self):
-        # bzrlib raises NotBranchError when accessing a nonexistent
+        # breezy raises NotBranchError when accessing a nonexistent
         # branch.  The exporter deals with that by calling
         # _handleUnpushedBranch.
         exporter = ExportTranslationsToBranch(test_args=[])
diff --git a/lib/lp/translations/scripts/translations_to_branch.py b/lib/lp/translations/scripts/translations_to_branch.py
index 973b45f..5f7a64f 100644
--- a/lib/lp/translations/scripts/translations_to_branch.py
+++ b/lib/lp/translations/scripts/translations_to_branch.py
@@ -17,8 +17,8 @@ import os.path
 # line below this comment.
 import lp.codehosting
 
-from bzrlib.errors import NotBranchError
-from bzrlib.revision import NULL_REVISION
+from breezy.errors import NotBranchError
+from breezy.revision import NULL_REVISION
 import pytz
 from storm.expr import (
     And,
diff --git a/lib/lp/translations/tests/test_rosetta_branches_script.py b/lib/lp/translations/tests/test_rosetta_branches_script.py
index 1d332d4..1d140cd 100644
--- a/lib/lp/translations/tests/test_rosetta_branches_script.py
+++ b/lib/lp/translations/tests/test_rosetta_branches_script.py
@@ -9,7 +9,7 @@ provisions to handle Bazaar branches.
 
 __metaclass__ = type
 
-from bzrlib.revision import NULL_REVISION
+from breezy.revision import NULL_REVISION
 import transaction
 from zope.component import getUtility
 
@@ -43,11 +43,11 @@ class TestRosettaBranchesScript(TestCaseWithFactory):
         self.useBzrBranches()
         pot_content = self.factory.getUniqueString()
         branch, tree = self.create_branch_and_tree()
-        tree.bzrdir.root_transport.put_bytes(pot_path, pot_content)
+        tree.controldir.root_transport.put_bytes(pot_path, pot_content)
         tree.add(pot_path)
         # XXX: AaronBentley 2010-08-06 bug=614404: a bzr username is
         # required to generate the revision-id.
-        with override_environ(BZR_EMAIL='me@xxxxxxxxxxx'):
+        with override_environ(BRZ_EMAIL='me@xxxxxxxxxxx'):
             revision_id = tree.commit("first commit")
         branch.last_scanned_id = revision_id
         branch.last_mirrored_id = revision_id
diff --git a/lib/lp_sitecustomize.py b/lib/lp_sitecustomize.py
index 67c0030..d23cd74 100644
--- a/lib/lp_sitecustomize.py
+++ b/lib/lp_sitecustomize.py
@@ -77,11 +77,12 @@ def silence_amqp_logger():
     amqp_logger.propagate = False
 
 
-def silence_bzr_logger():
-    """Install the NullHandler on the bzr logger to silence logs."""
-    bzr_logger = logging.getLogger('bzr')
-    bzr_logger.addHandler(logging.NullHandler())
-    bzr_logger.propagate = False
+def silence_bzr_loggers():
+    """Install the NullHandler on the bzr/brz loggers to silence logs."""
+    for logger_name in ('bzr', 'brz'):
+        logger = logging.getLogger(logger_name)
+        logger.addHandler(logging.NullHandler())
+        logger.propagate = False
 
 
 def silence_swiftclient_logger():
@@ -154,7 +155,7 @@ def customize_logger():
     logging between tests.
     """
     silence_amqp_logger()
-    silence_bzr_logger()
+    silence_bzr_loggers()
     silence_zcml_logger()
     silence_transaction_logger()
     silence_swiftclient_logger()
@@ -185,3 +186,9 @@ def main(instance_name=None):
     # through actually using itertools.groupby.
     grouper = type(list(itertools.groupby([0]))[0][1])
     checker.BasicTypes[grouper] = checker._iteratorChecker
+
+    # XXX 2019-09-17: git must be disabled until codeimport is upgraded,
+    # since the required dulwich versions for our current version of bzr-git
+    # and for Breezy are incompatible in both directions.
+    import types
+    sys.modules['breezy.git'] = types.ModuleType('breezy.git')
diff --git a/scripts/mirror-branch.py b/scripts/mirror-branch.py
index a493cf0..90f8cef 100755
--- a/scripts/mirror-branch.py
+++ b/scripts/mirror-branch.py
@@ -33,7 +33,7 @@ import os
 import resource
 import sys
 
-import bzrlib.repository
+import breezy.repository
 
 from lp.code.enums import BranchType
 from lp.codehosting.puller.worker import (
@@ -54,24 +54,7 @@ def shut_up_deprecation_warning():
     # XXX DavidAllouche 2006-01-29:
     # Quick hack to disable the deprecation warning for old repository
     # formats.
-    bzrlib.repository._deprecation_warning_done = True
-
-
-def force_bzr_to_use_urllib():
-    # These lines prevent bzr from using pycurl to connect to http: urls.  We
-    # want this for two reasons:
-    # 1) pycurl rejects self signed certificates, which prevents a significant
-    #    number of mirror branchs from updating, and
-    # 2) the script sometimes hangs inside pycurl, preventing all mirrors from
-    #    being updated until the script is restarted.
-    # There is no test for this (it would involve a great number of moving
-    # parts) but it has been verified to work on production.  Also see
-    # https://bugs.launchpad.net/bzr/+bug/82086
-    from bzrlib.transport import register_lazy_transport
-    register_lazy_transport('http://', 'bzrlib.transport.http._urllib',
-                            'HttpTransport_urllib')
-    register_lazy_transport('https://', 'bzrlib.transport.http._urllib',
-                            'HttpTransport_urllib')
+    breezy.repository._deprecation_warning_done = True
 
 
 if __name__ == '__main__':
@@ -86,7 +69,6 @@ if __name__ == '__main__':
     section_name = 'supermirror_%s_puller' % branch_type_map[branch_type]
     globalErrorUtility.configure(section_name)
     shut_up_deprecation_warning()
-    force_bzr_to_use_urllib()
 
     resource.setrlimit(resource.RLIMIT_AS, (1500000000, 1500000000))
 
diff --git a/scripts/update-stacked-on.py b/scripts/update-stacked-on.py
index 41e11fa..dda181d 100755
--- a/scripts/update-stacked-on.py
+++ b/scripts/update-stacked-on.py
@@ -23,9 +23,10 @@ import _pythonpath
 from collections import namedtuple
 import sys
 
-from bzrlib import errors
-from bzrlib.bzrdir import BzrDir
-from bzrlib.config import TransportConfig
+from breezy import errors
+from breezy.branch import UnstackableBranchFormat
+from breezy.bzr.bzrdir import BzrDir
+from breezy.config import TransportConfig
 
 from lp.code.interfaces.codehosting import branch_id_alias
 from lp.codehosting.bzrutils import get_branch_stacked_on_url
@@ -109,7 +110,7 @@ class UpdateStackedBranches(LaunchpadScript):
             self.logger.warn(
                 "Branch for %r at %r is not stacked at all. Giving up."
                 % (branch_id, bzr_branch_url))
-        except errors.UnstackableBranchFormat:
+        except UnstackableBranchFormat:
             self.logger.error(
                 "Branch for %r at %r is unstackable. Giving up."
                 % (branch_id, bzr_branch_url))
diff --git a/setup.py b/setup.py
index 6859381..fb390ea 100644
--- a/setup.py
+++ b/setup.py
@@ -149,6 +149,7 @@ setup(
         'backports.lzma',
         'BeautifulSoup',
         'beautifulsoup4[lxml]',
+        'breezy',
         'bzr',
         'celery',
         'cssselect',
@@ -277,6 +278,7 @@ setup(
         'zope.vocabularyregistry',
         # Loggerhead dependencies. These should be removed once
         # bug 383360 is fixed and we include it as a source dist.
+        'bleach',
         'Paste',
         'PasteDeploy',
         'SimpleTAL',
diff --git a/utilities/create-lp-wadl-and-apidoc.py b/utilities/create-lp-wadl-and-apidoc.py
index 808c991..4894943 100755
--- a/utilities/create-lp-wadl-and-apidoc.py
+++ b/utilities/create-lp-wadl-and-apidoc.py
@@ -18,8 +18,8 @@ import os
 import subprocess
 import sys
 
-import bzrlib
-from bzrlib.branch import Branch
+import breezy
+from breezy.branch import Branch
 from lazr.restful.interfaces import IWebServiceConfiguration
 from z3c.ptcompat import PageTemplateFile
 from zope.component import getUtility
@@ -144,7 +144,7 @@ def main(directory, force=False):
             ["git", "log", "-1", "--format=%ct", "HEAD"],
             universal_newlines=True))
     else:
-        with bzrlib.initialize():
+        with breezy.get_global_state():
             branch = Branch.open(top)
             timestamp = branch.repository.get_revision(
                 branch.last_revision()).timestamp
diff --git a/utilities/sourcedeps.cache b/utilities/sourcedeps.cache
index 1360489..e530fd8 100644
--- a/utilities/sourcedeps.cache
+++ b/utilities/sourcedeps.cache
@@ -1,16 +1,16 @@
 {
-    "bzr-builder": [
-        70, 
-        "launchpad@xxxxxxxxxxxxxxxxx-20111114140506-6bmt9isw6lcud7yt"
+    "brz-builder": [
+        180, 
+        "jelmer@xxxxxxxxx-20180624153632-1f0weftl0pawz6wj"
+    ], 
+    "brz-loom": [
+        164, 
+        "jelmer@xxxxxxxxx-20190613193059-rmsz6mcj33cj1rod"
     ], 
     "bzr-git": [
         280, 
         "launchpad@xxxxxxxxxxxxxxxxx-20171222005919-u98ut0f5z2g618um"
     ], 
-    "bzr-loom": [
-        55, 
-        "launchpad@xxxxxxxxxxxxxxxxx-20120830090804-cg49kky93htwax7s"
-    ], 
     "bzr-svn": [
         2725, 
         "launchpad@xxxxxxxxxxxxxxxxx-20130816045016-wzr810hu2z459t4y"
@@ -24,8 +24,8 @@
         "cjwatson@xxxxxxxxxxxxx-20190614154330-091l9edcnubsjmsx"
     ], 
     "loggerhead": [
-        493, 
-        "cjwatson@xxxxxxxxxxxxx-20190621112125-3aaxj3hrmty19lr6"
+        494, 
+        "cjwatson@xxxxxxxxxxxxx-20190919081036-q1symc2h2iedtlh3"
     ], 
     "mailman": [
         977, 
diff --git a/utilities/sourcedeps.conf b/utilities/sourcedeps.conf
index d1dc1df..c59c4f2 100644
--- a/utilities/sourcedeps.conf
+++ b/utilities/sourcedeps.conf
@@ -7,13 +7,13 @@
 ####  DEPRECATED. NO NEW ITEMS. NO NO NO NO NO NONONONONO
 #########################################################
 
-bzr-builder lp:~launchpad-pqm/bzr-builder/trunk;revno=70
+brz-builder lp:~jelmer/brz-builder/trunk;revno=180
+brz-loom lp:~jelmer/brz-loom/trunk;revno=164
 bzr-git lp:~launchpad-pqm/bzr-git/devel;revno=280
-bzr-loom lp:~launchpad-pqm/bzr-loom/trunk;revno=55
 bzr-svn lp:~launchpad-pqm/bzr-svn/devel;revno=2725
 cscvs lp:~launchpad-pqm/launchpad-cscvs/devel;revno=433
 difftacular lp:~launchpad/difftacular/trunk;revno=11
-loggerhead lp:~loggerhead-team/loggerhead/trunk-rich;revno=493
+loggerhead lp:~loggerhead-team/loggerhead/trunk-rich;revno=494
 mailman lp:~launchpad-pqm/mailman/2.1;revno=977
 old_xmlplus lp:~launchpad-pqm/dtdparser/trunk;revno=4
 pygettextpo lp:~launchpad-pqm/pygettextpo/trunk;revno=25

References