[MERGE] ChrootTransportDecorator

Andrew Bennetts andrew at canonical.com
Fri Oct 13 07:56:53 BST 2006


This bundle adds a ChrootTransportDecorator.  I use this in the latest revision
of my WSGI branch, so that the smart server won't provide a way to access any
file on your filesystem.

The bundle is relative to the MemoryTransport.abspath fix posted earlier.

-Andrew.

-------------- next part --------------
# Bazaar revision bundle v0.8
#
# message:
#   Merge from 'memory transport abspath'.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2006-10-13 15:44:24.796000004 +1000

=== added file bzrlib/transport/chroot.py // file-id:chroot.py-20061011104729-0
... us9mgm97z378vnt-1 // last-changed:andrew.bennetts at canonical.com-20061012060
... 928-e387650ef98b70f5
--- /dev/null
+++ bzrlib/transport/chroot.py
@@ -0,0 +1,136 @@
+# Copyright (C) 2006 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Implementation of Transport that prevents access to locations above a set
+root.
+"""
+
+from bzrlib import errors, urlutils
+from bzrlib.transport.decorator import TransportDecorator, DecoratorServer
+
+
+class ChrootTransportDecorator(TransportDecorator):
+    """A decorator that can convert any transport to be chrooted.
+
+    This is requested via the 'chrooted+' prefix to get_transport().
+    """
+
+    def __init__(self, url, _decorated=None, chroot=None):
+        super(ChrootTransportDecorator, self).__init__(url,
+                _decorated=_decorated)
+        if chroot is None:
+            self.chroot_url = self._decorated.base
+        else:
+            self.chroot_url = chroot
+
+    @classmethod
+    def _get_url_prefix(self):
+        """Chroot transport decorators are invoked via 'chroot+'"""
+        return 'chroot+'
+
+    def _ensure_relpath_is_child(self, relpath):
+        abspath = self.abspath(relpath)
+        chroot_base = self._get_url_prefix() + self.chroot_url
+        real_relpath = urlutils.relative_url(chroot_base, abspath)
+        if real_relpath == '..' or real_relpath.startswith('../'):
+            raise errors.PathNotChild(relpath, self.chroot_url)
+
+    # decorated methods
+    def append_file(self, relpath, f, mode=None):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.append_file(self, relpath, f, mode=mode)
+
+    def append_bytes(self, relpath, bytes, mode=None):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.append_bytes(self, relpath, bytes, mode=mode)
+
+    def clone(self, offset=None):
+        self._ensure_relpath_is_child(offset)
+        return TransportDecorator.clone(self, offset)
+
+    def delete(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.delete(self, relpath)
+
+    def delete_tree(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.delete_tree(self, relpath)
+
+    def get(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.get(self, relpath)
+
+    def get_bytes(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.get_bytes(self, relpath)
+
+    def get(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.get(self, relpath)
+
+    def has(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.has(self, relpath)
+
+    def list_dir(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.list_dir(self, relpath)
+
+    def lock_read(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.lock_read(self, relpath)
+
+    def lock_write(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.lock_write(self, relpath)
+
+    def mkdir(self, relpath, mode=None):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.mkdir(self, relpath, mode=mode)
+
+    def put_bytes(self, relpath, bytes, mode=None):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.put_bytes(self, relpath, bytes, mode=mode)
+
+    def put_file(self, relpath, f, mode=None):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.put_file(self, relpath, f, mode=mode)
+
+    def rename(self, rel_from, rel_to):
+        self._ensure_relpath_is_child(rel_from)
+        self._ensure_relpath_is_child(rel_to)
+        return TransportDecorator.rename(self, rel_from, rel_to)
+
+    def rmdir(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.rmdir(self, relpath)
+
+    def stat(self, relpath):
+        self._ensure_relpath_is_child(relpath)
+        return TransportDecorator.stat(self, relpath)
+
+
+class ChrootServer(DecoratorServer):
+    """Server for the ReadonlyTransportDecorator for testing with."""
+
+    def get_decorator_class(self):
+        return ChrootTransportDecorator
+
+
+def get_test_permutations():
+    """Return the permutations to be used in testing."""
+    return [(ChrootTransportDecorator, ChrootServer),
+            ]

=== modified file NEWS // last-changed:andrew.bennetts at canonical.com-2006101206
... 0928-e387650ef98b70f5
--- NEWS
+++ NEWS
@@ -13,6 +13,10 @@
       around a regex, which defers compilation until first use. 
       (John Arbash Meinel)
 
+    * New ``ChrootTransportDecorator``, accessible via the ``chroot+`` url
+      prefix.  It disallows any access to locations above a set URL.  (Andrew
+      Bennetts)
+
   BUG FIXES:
 
     * bzr branch/pull no longer complain about progress bar cleanup when

=== modified file bzrlib/tests/test_transport.py
--- bzrlib/tests/test_transport.py
+++ bzrlib/tests/test_transport.py
@@ -21,12 +21,15 @@
 from cStringIO import StringIO
 
 import bzrlib
-from bzrlib.errors import (NoSuchFile, FileExists,
-                           TransportNotPossible,
-                           ConnectionError,
-                           DependencyNotPresent,
-                           UnsupportedProtocol,
-                           )
+from bzrlib.errors import (
+    ConnectionError,
+    DependencyNotPresent,
+    FileExists,
+    NoSuchFile,
+    PathNotChild,
+    TransportNotPossible,
+    UnsupportedProtocol,
+    )
 from bzrlib.tests import TestCase, TestCaseInTempDir
 from bzrlib.transport import (_CoalescedOffset,
                               _get_protocol_handlers,
@@ -258,6 +261,88 @@
         self.assertEqual(7, transport.stat('foo').st_size)
         self.assertEqual(6, transport.stat('bar').st_size)
 
+
+class ChrootDecoratorTransportTest(TestCase):
+    """Chroot decoration specific tests."""
+
+    def test_construct(self):
+        from bzrlib.transport import chroot
+        transport = chroot.ChrootTransportDecorator('chroot+memory:///pathA/')
+        self.assertEqual('memory:///pathA/', transport.chroot_url)
+
+        transport = chroot.ChrootTransportDecorator(
+            'chroot+memory:///path/B', chroot='memory:///path/')
+        self.assertEqual('memory:///path/', transport.chroot_url)
+
+    def test_append_file(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.append_file, '/foo', None)
+
+    def test_append_bytes(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.append_bytes, '/foo', 'bytes')
+
+    def test_clone(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.clone, '/foo')
+
+    def test_delete(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.delete, '/foo')
+
+    def test_delete_tree(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.delete_tree, '/foo')
+
+    def test_get(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.get, '/foo')
+
+    def test_get_bytes(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.get_bytes, '/foo')
+
+    def test_has(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.has, '/foo')
+
+    def test_list_dir(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.list_dir, '/foo')
+
+    def test_lock_read(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.lock_read, '/foo')
+
+    def test_lock_write(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.lock_write, '/foo')
+
+    def test_mkdir(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.mkdir, '/foo')
+
+    def test_put_bytes(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.put_bytes, '/foo', 'bytes')
+
+    def test_put_file(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.put_file, '/foo', None)
+
+    def test_rename(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.rename, '/aaa', 'bbb')
+        self.assertRaises(PathNotChild, transport.rename, 'ccc', '/d')
+
+    def test_rmdir(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.rmdir, '/foo')
+
+    def test_stat(self):
+        transport = get_transport('chroot+file:///foo/bar')
+        self.assertRaises(PathNotChild, transport.stat, '/foo')
+
         
 class ReadonlyDecoratorTransportTest(TestCase):
     """Readonly decoration specific tests."""

=== modified file bzrlib/tests/test_transport_implementations.py
--- bzrlib/tests/test_transport_implementations.py
+++ bzrlib/tests/test_transport_implementations.py
@@ -38,7 +38,7 @@
 from bzrlib.symbol_versioning import zero_eleven
 from bzrlib.tests import TestCaseInTempDir, TestSkipped
 from bzrlib.tests.test_transport import TestTransportImplementation
-from bzrlib.transport import memory, smart
+from bzrlib.transport import memory, smart, chroot
 import bzrlib.transport
 
 
@@ -94,7 +94,8 @@
 
     def test_has_root_works(self):
         current_transport = self.get_transport()
-        # import pdb;pdb.set_trace()
+        if isinstance(current_transport, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
         self.assertTrue(current_transport.has('/'))
         root = current_transport.clone('/')
         self.assertTrue(root.has(''))
@@ -1012,6 +1013,8 @@
     def test_clone(self):
         # TODO: Test that clone moves up and down the filesystem
         t1 = self.get_transport()
+        if isinstance(t1, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
 
         self.build_tree(['a', 'b/', 'b/c'], transport=t1)
 
@@ -1044,6 +1047,8 @@
 
     def test_clone_to_root(self):
         orig_transport = self.get_transport()
+        if isinstance(orig_transport, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
         # Repeatedly go up to a parent directory until we're at the root
         # directory of this transport
         root_transport = orig_transport
@@ -1072,6 +1077,8 @@
     def test_clone_from_root(self):
         """At the root, cloning to a simple dir should just do string append."""
         orig_transport = self.get_transport()
+        if isinstance(orig_transport, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('/')")
         root_transport = orig_transport.clone('/')
         self.assertEqual(root_transport.base + '.bzr/',
             root_transport.clone('.bzr').base)
@@ -1092,6 +1099,8 @@
 
     def test_relpath_at_root(self):
         t = self.get_transport()
+        if isinstance(t, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
         # clone all the way to the top
         new_transport = t.clone('..')
         while new_transport.base != t.base:
@@ -1107,6 +1116,8 @@
         # that have aliasing problems like symlinks should go in backend
         # specific test cases.
         transport = self.get_transport()
+        if isinstance(transport, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
         
         self.assertEqual(transport.base + 'relpath',
                          transport.abspath('relpath'))
@@ -1131,6 +1142,8 @@
 
     def test_abspath_at_root(self):
         t = self.get_transport()
+        if isinstance(t, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
         # clone all the way to the top
         new_transport = t.clone('..')
         while new_transport.base != t.base:
@@ -1235,6 +1248,8 @@
         # check that our server (whatever it is) is accessable reliably
         # via get_transport and multiple connections share content.
         transport = self.get_transport()
+        if isinstance(transport, chroot.ChrootTransportDecorator):
+            raise TestSkipped("ChrootTransportDecorator disallows clone('..')")
         if transport.is_readonly():
             return
         transport.put_bytes('foo', 'bar')

=== modified file bzrlib/transport/__init__.py
--- bzrlib/transport/__init__.py
+++ bzrlib/transport/__init__.py
@@ -1170,6 +1170,8 @@
 register_lazy_transport('ftp://', 'bzrlib.transport.ftp', 'FtpTransport')
 register_lazy_transport('aftp://', 'bzrlib.transport.ftp', 'FtpTransport')
 register_lazy_transport('memory://', 'bzrlib.transport.memory', 'MemoryTransport')
+register_lazy_transport('chroot+', 'bzrlib.transport.chroot',
+                        'ChrootTransportDecorator')
 register_lazy_transport('readonly+', 'bzrlib.transport.readonly', 'ReadonlyTransportDecorator')
 register_lazy_transport('fakenfs+', 'bzrlib.transport.fakenfs', 'FakeNFSTransportDecorator')
 register_lazy_transport('vfat+',

# revision id: andrew.bennetts at canonical.com-20061013054424-f5728f4a9d1dd739
# sha1: 71a2bafc348d72fdeeb37545f8d369cd6d432953
# inventory sha1: 6e32a30deb48b99d33203ea46e2bf8c4e2f832ff
# parent ids:
#   andrew.bennetts at canonical.com-20061012060928-e387650ef98b70f5
#   andrew.bennetts at canonical.com-20061013052902-60a2d663ee8d494b
# base id: andrew.bennetts at canonical.com-20061013052902-60a2d663ee8d494b
# properties:
#   branch-nick: chroot decorator

# message:
#   Add ChrootTransportDecorator.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-10-12 16:09:28.492000103 +1000

=== added file bzrlib/transport/chroot.py // file-id:chroot.py-20061011104729-0
... us9mgm97z378vnt-1 // encoding:base64
LS0tIC9kZXYvbnVsbAorKysgYnpybGliL3RyYW5zcG9ydC9jaHJvb3QucHkKQEAgLTAsMCArMSwx
MzYgQEAKKyMgQ29weXJpZ2h0IChDKSAyMDA2IENhbm9uaWNhbCBMdGQKKyMKKyMgVGhpcyBwcm9n
cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp
ZnkKKyMgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5z
ZSBhcyBwdWJsaXNoZWQgYnkKKyMgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVy
IHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKKyMgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0
ZXIgdmVyc2lvbi4KKyMKKyMgVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3Bl
IHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCisjIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0
aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisjIE1FUkNIQU5UQUJJTElUWSBvciBG
SVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKKyMgR05VIEdlbmVyYWwg
UHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KKyMKKyMgWW91IHNob3VsZCBoYXZlIHJl
Y2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKKyMgYWxvbmcg
d2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKKyMg
Rm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEg
IDAyMTExLTEzMDcgIFVTQQorCisiIiJJbXBsZW1lbnRhdGlvbiBvZiBUcmFuc3BvcnQgdGhhdCBw
cmV2ZW50cyBhY2Nlc3MgdG8gbG9jYXRpb25zIGFib3ZlIGEgc2V0Cityb290LgorIiIiCisKK2Zy
b20gYnpybGliIGltcG9ydCBlcnJvcnMsIHVybHV0aWxzCitmcm9tIGJ6cmxpYi50cmFuc3BvcnQu
ZGVjb3JhdG9yIGltcG9ydCBUcmFuc3BvcnREZWNvcmF0b3IsIERlY29yYXRvclNlcnZlcgorCisK
K2NsYXNzIENocm9vdFRyYW5zcG9ydERlY29yYXRvcihUcmFuc3BvcnREZWNvcmF0b3IpOgorICAg
ICIiIkEgZGVjb3JhdG9yIHRoYXQgY2FuIGNvbnZlcnQgYW55IHRyYW5zcG9ydCB0byBiZSBjaHJv
b3RlZC4KKworICAgIFRoaXMgaXMgcmVxdWVzdGVkIHZpYSB0aGUgJ2Nocm9vdGVkKycgcHJlZml4
IHRvIGdldF90cmFuc3BvcnQoKS4KKyAgICAiIiIKKworICAgIGRlZiBfX2luaXRfXyhzZWxmLCB1
cmwsIF9kZWNvcmF0ZWQ9Tm9uZSwgY2hyb290PU5vbmUpOgorICAgICAgICBzdXBlcihDaHJvb3RU
cmFuc3BvcnREZWNvcmF0b3IsIHNlbGYpLl9faW5pdF9fKHVybCwKKyAgICAgICAgICAgICAgICBf
ZGVjb3JhdGVkPV9kZWNvcmF0ZWQpCisgICAgICAgIGlmIGNocm9vdCBpcyBOb25lOgorICAgICAg
ICAgICAgc2VsZi5jaHJvb3RfdXJsID0gc2VsZi5fZGVjb3JhdGVkLmJhc2UKKyAgICAgICAgZWxz
ZToKKyAgICAgICAgICAgIHNlbGYuY2hyb290X3VybCA9IGNocm9vdAorCisgICAgQGNsYXNzbWV0
aG9kCisgICAgZGVmIF9nZXRfdXJsX3ByZWZpeChzZWxmKToKKyAgICAgICAgIiIiQ2hyb290IHRy
YW5zcG9ydCBkZWNvcmF0b3JzIGFyZSBpbnZva2VkIHZpYSAnY2hyb290KyciIiIKKyAgICAgICAg
cmV0dXJuICdjaHJvb3QrJworCisgICAgZGVmIF9lbnN1cmVfcmVscGF0aF9pc19jaGlsZChzZWxm
LCByZWxwYXRoKToKKyAgICAgICAgYWJzcGF0aCA9IHNlbGYuYWJzcGF0aChyZWxwYXRoKQorICAg
ICAgICBjaHJvb3RfYmFzZSA9IHNlbGYuX2dldF91cmxfcHJlZml4KCkgKyBzZWxmLmNocm9vdF91
cmwKKyAgICAgICAgcmVhbF9yZWxwYXRoID0gdXJsdXRpbHMucmVsYXRpdmVfdXJsKGNocm9vdF9i
YXNlLCBhYnNwYXRoKQorICAgICAgICBpZiByZWFsX3JlbHBhdGggPT0gJy4uJyBvciByZWFsX3Jl
bHBhdGguc3RhcnRzd2l0aCgnLi4vJyk6CisgICAgICAgICAgICByYWlzZSBlcnJvcnMuUGF0aE5v
dENoaWxkKHJlbHBhdGgsIHNlbGYuY2hyb290X3VybCkKKworICAgICMgZGVjb3JhdGVkIG1ldGhv
ZHMKKyAgICBkZWYgYXBwZW5kX2ZpbGUoc2VsZiwgcmVscGF0aCwgZiwgbW9kZT1Ob25lKToKKyAg
ICAgICAgc2VsZi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQocmVscGF0aCkKKyAgICAgICAgcmV0
dXJuIFRyYW5zcG9ydERlY29yYXRvci5hcHBlbmRfZmlsZShzZWxmLCByZWxwYXRoLCBmLCBtb2Rl
PW1vZGUpCisKKyAgICBkZWYgYXBwZW5kX2J5dGVzKHNlbGYsIHJlbHBhdGgsIGJ5dGVzLCBtb2Rl
PU5vbmUpOgorICAgICAgICBzZWxmLl9lbnN1cmVfcmVscGF0aF9pc19jaGlsZChyZWxwYXRoKQor
ICAgICAgICByZXR1cm4gVHJhbnNwb3J0RGVjb3JhdG9yLmFwcGVuZF9ieXRlcyhzZWxmLCByZWxw
YXRoLCBieXRlcywgbW9kZT1tb2RlKQorCisgICAgZGVmIGNsb25lKHNlbGYsIG9mZnNldD1Ob25l
KToKKyAgICAgICAgc2VsZi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQob2Zmc2V0KQorICAgICAg
ICByZXR1cm4gVHJhbnNwb3J0RGVjb3JhdG9yLmNsb25lKHNlbGYsIG9mZnNldCkKKworICAgIGRl
ZiBkZWxldGUoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHNlbGYuX2Vuc3VyZV9yZWxwYXRoX2lz
X2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJldHVybiBUcmFuc3BvcnREZWNvcmF0b3IuZGVsZXRl
KHNlbGYsIHJlbHBhdGgpCisKKyAgICBkZWYgZGVsZXRlX3RyZWUoc2VsZiwgcmVscGF0aCk6Cisg
ICAgICAgIHNlbGYuX2Vuc3VyZV9yZWxwYXRoX2lzX2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJl
dHVybiBUcmFuc3BvcnREZWNvcmF0b3IuZGVsZXRlX3RyZWUoc2VsZiwgcmVscGF0aCkKKworICAg
IGRlZiBnZXQoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHNlbGYuX2Vuc3VyZV9yZWxwYXRoX2lz
X2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJldHVybiBUcmFuc3BvcnREZWNvcmF0b3IuZ2V0KHNl
bGYsIHJlbHBhdGgpCisKKyAgICBkZWYgZ2V0X2J5dGVzKHNlbGYsIHJlbHBhdGgpOgorICAgICAg
ICBzZWxmLl9lbnN1cmVfcmVscGF0aF9pc19jaGlsZChyZWxwYXRoKQorICAgICAgICByZXR1cm4g
VHJhbnNwb3J0RGVjb3JhdG9yLmdldF9ieXRlcyhzZWxmLCByZWxwYXRoKQorCisgICAgZGVmIGdl
dChzZWxmLCByZWxwYXRoKToKKyAgICAgICAgc2VsZi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQo
cmVscGF0aCkKKyAgICAgICAgcmV0dXJuIFRyYW5zcG9ydERlY29yYXRvci5nZXQoc2VsZiwgcmVs
cGF0aCkKKworICAgIGRlZiBoYXMoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHNlbGYuX2Vuc3Vy
ZV9yZWxwYXRoX2lzX2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJldHVybiBUcmFuc3BvcnREZWNv
cmF0b3IuaGFzKHNlbGYsIHJlbHBhdGgpCisKKyAgICBkZWYgbGlzdF9kaXIoc2VsZiwgcmVscGF0
aCk6CisgICAgICAgIHNlbGYuX2Vuc3VyZV9yZWxwYXRoX2lzX2NoaWxkKHJlbHBhdGgpCisgICAg
ICAgIHJldHVybiBUcmFuc3BvcnREZWNvcmF0b3IubGlzdF9kaXIoc2VsZiwgcmVscGF0aCkKKwor
ICAgIGRlZiBsb2NrX3JlYWQoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHNlbGYuX2Vuc3VyZV9y
ZWxwYXRoX2lzX2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJldHVybiBUcmFuc3BvcnREZWNvcmF0
b3IubG9ja19yZWFkKHNlbGYsIHJlbHBhdGgpCisKKyAgICBkZWYgbG9ja193cml0ZShzZWxmLCBy
ZWxwYXRoKToKKyAgICAgICAgc2VsZi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQocmVscGF0aCkK
KyAgICAgICAgcmV0dXJuIFRyYW5zcG9ydERlY29yYXRvci5sb2NrX3dyaXRlKHNlbGYsIHJlbHBh
dGgpCisKKyAgICBkZWYgbWtkaXIoc2VsZiwgcmVscGF0aCwgbW9kZT1Ob25lKToKKyAgICAgICAg
c2VsZi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQocmVscGF0aCkKKyAgICAgICAgcmV0dXJuIFRy
YW5zcG9ydERlY29yYXRvci5ta2RpcihzZWxmLCByZWxwYXRoLCBtb2RlPW1vZGUpCisKKyAgICBk
ZWYgcHV0X2J5dGVzKHNlbGYsIHJlbHBhdGgsIGJ5dGVzLCBtb2RlPU5vbmUpOgorICAgICAgICBz
ZWxmLl9lbnN1cmVfcmVscGF0aF9pc19jaGlsZChyZWxwYXRoKQorICAgICAgICByZXR1cm4gVHJh
bnNwb3J0RGVjb3JhdG9yLnB1dF9ieXRlcyhzZWxmLCByZWxwYXRoLCBieXRlcywgbW9kZT1tb2Rl
KQorCisgICAgZGVmIHB1dF9maWxlKHNlbGYsIHJlbHBhdGgsIGYsIG1vZGU9Tm9uZSk6CisgICAg
ICAgIHNlbGYuX2Vuc3VyZV9yZWxwYXRoX2lzX2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJldHVy
biBUcmFuc3BvcnREZWNvcmF0b3IucHV0X2ZpbGUoc2VsZiwgcmVscGF0aCwgZiwgbW9kZT1tb2Rl
KQorCisgICAgZGVmIHJlbmFtZShzZWxmLCByZWxfZnJvbSwgcmVsX3RvKToKKyAgICAgICAgc2Vs
Zi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQocmVsX2Zyb20pCisgICAgICAgIHNlbGYuX2Vuc3Vy
ZV9yZWxwYXRoX2lzX2NoaWxkKHJlbF90bykKKyAgICAgICAgcmV0dXJuIFRyYW5zcG9ydERlY29y
YXRvci5yZW5hbWUoc2VsZiwgcmVsX2Zyb20sIHJlbF90bykKKworICAgIGRlZiBybWRpcihzZWxm
LCByZWxwYXRoKToKKyAgICAgICAgc2VsZi5fZW5zdXJlX3JlbHBhdGhfaXNfY2hpbGQocmVscGF0
aCkKKyAgICAgICAgcmV0dXJuIFRyYW5zcG9ydERlY29yYXRvci5ybWRpcihzZWxmLCByZWxwYXRo
KQorCisgICAgZGVmIHN0YXQoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHNlbGYuX2Vuc3VyZV9y
ZWxwYXRoX2lzX2NoaWxkKHJlbHBhdGgpCisgICAgICAgIHJldHVybiBUcmFuc3BvcnREZWNvcmF0
b3Iuc3RhdChzZWxmLCByZWxwYXRoKQorCisKK2NsYXNzIENocm9vdFNlcnZlcihEZWNvcmF0b3JT
ZXJ2ZXIpOgorICAgICIiIlNlcnZlciBmb3IgdGhlIFJlYWRvbmx5VHJhbnNwb3J0RGVjb3JhdG9y
IGZvciB0ZXN0aW5nIHdpdGguIiIiCisKKyAgICBkZWYgZ2V0X2RlY29yYXRvcl9jbGFzcyhzZWxm
KToKKyAgICAgICAgcmV0dXJuIENocm9vdFRyYW5zcG9ydERlY29yYXRvcgorCisKK2RlZiBnZXRf
dGVzdF9wZXJtdXRhdGlvbnMoKToKKyAgICAiIiJSZXR1cm4gdGhlIHBlcm11dGF0aW9ucyB0byBi
ZSB1c2VkIGluIHRlc3RpbmcuIiIiCisgICAgcmV0dXJuIFsoQ2hyb290VHJhbnNwb3J0RGVjb3Jh
dG9yLCBDaHJvb3RTZXJ2ZXIpLAorICAgICAgICAgICAgXQoK

=== modified file NEWS // encoding:base64
LS0tIE5FV1MKKysrIE5FV1MKQEAgLTEzLDYgKzEzLDEwIEBACiAgICAgICBhcm91bmQgYSByZWdl
eCwgd2hpY2ggZGVmZXJzIGNvbXBpbGF0aW9uIHVudGlsIGZpcnN0IHVzZS4gCiAgICAgICAoSm9o
biBBcmJhc2ggTWVpbmVsKQogCisgICAgKiBOZXcgYGBDaHJvb3RUcmFuc3BvcnREZWNvcmF0b3Jg
YCwgYWNjZXNzaWJsZSB2aWEgdGhlIGBgY2hyb290K2BgIHVybAorICAgICAgcHJlZml4LiAgSXQg
ZGlzYWxsb3dzIGFueSBhY2Nlc3MgdG8gbG9jYXRpb25zIGFib3ZlIGEgc2V0IFVSTC4gIChBbmRy
ZXcKKyAgICAgIEJlbm5ldHRzKQorCiAgIEJVRyBGSVhFUzoKIAogICAgICogYnpyIGJyYW5jaC9w
dWxsIG5vIGxvbmdlciBjb21wbGFpbiBhYm91dCBwcm9ncmVzcyBiYXIgY2xlYW51cCB3aGVuCgo=

=== modified file bzrlib/tests/test_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydC5weQorKysgYnpybGliL3Rlc3RzL3Rlc3Rf
dHJhbnNwb3J0LnB5CkBAIC0yMSwxMiArMjEsMTUgQEAKIGZyb20gY1N0cmluZ0lPIGltcG9ydCBT
dHJpbmdJTwogCiBpbXBvcnQgYnpybGliCi1mcm9tIGJ6cmxpYi5lcnJvcnMgaW1wb3J0IChOb1N1
Y2hGaWxlLCBGaWxlRXhpc3RzLAotICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhbnNwb3J0
Tm90UG9zc2libGUsCi0gICAgICAgICAgICAgICAgICAgICAgICAgICBDb25uZWN0aW9uRXJyb3Is
Ci0gICAgICAgICAgICAgICAgICAgICAgICAgICBEZXBlbmRlbmN5Tm90UHJlc2VudCwKLSAgICAg
ICAgICAgICAgICAgICAgICAgICAgIFVuc3VwcG9ydGVkUHJvdG9jb2wsCi0gICAgICAgICAgICAg
ICAgICAgICAgICAgICApCitmcm9tIGJ6cmxpYi5lcnJvcnMgaW1wb3J0ICgKKyAgICBDb25uZWN0
aW9uRXJyb3IsCisgICAgRGVwZW5kZW5jeU5vdFByZXNlbnQsCisgICAgRmlsZUV4aXN0cywKKyAg
ICBOb1N1Y2hGaWxlLAorICAgIFBhdGhOb3RDaGlsZCwKKyAgICBUcmFuc3BvcnROb3RQb3NzaWJs
ZSwKKyAgICBVbnN1cHBvcnRlZFByb3RvY29sLAorICAgICkKIGZyb20gYnpybGliLnRlc3RzIGlt
cG9ydCBUZXN0Q2FzZSwgVGVzdENhc2VJblRlbXBEaXIKIGZyb20gYnpybGliLnRyYW5zcG9ydCBp
bXBvcnQgKF9Db2FsZXNjZWRPZmZzZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBf
Z2V0X3Byb3RvY29sX2hhbmRsZXJzLApAQCAtMjU3LDYgKzI2MCw4OCBAQAogICAgICAgICBzZWxm
LmFzc2VydEVxdWFsKDcsIHRyYW5zcG9ydC5zdGF0KCdmb28nKS5zdF9zaXplKQogICAgICAgICBz
ZWxmLmFzc2VydEVxdWFsKDYsIHRyYW5zcG9ydC5zdGF0KCdiYXInKS5zdF9zaXplKQogCisKK2Ns
YXNzIENocm9vdERlY29yYXRvclRyYW5zcG9ydFRlc3QoVGVzdENhc2UpOgorICAgICIiIkNocm9v
dCBkZWNvcmF0aW9uIHNwZWNpZmljIHRlc3RzLiIiIgorCisgICAgZGVmIHRlc3RfY29uc3RydWN0
KHNlbGYpOgorICAgICAgICBmcm9tIGJ6cmxpYi50cmFuc3BvcnQgaW1wb3J0IGNocm9vdAorICAg
ICAgICB0cmFuc3BvcnQgPSBjaHJvb3QuQ2hyb290VHJhbnNwb3J0RGVjb3JhdG9yKCdjaHJvb3Qr
bWVtb3J5Oi8vL3BhdGhBLycpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJ21lbW9yeTovLy9w
YXRoQS8nLCB0cmFuc3BvcnQuY2hyb290X3VybCkKKworICAgICAgICB0cmFuc3BvcnQgPSBjaHJv
b3QuQ2hyb290VHJhbnNwb3J0RGVjb3JhdG9yKAorICAgICAgICAgICAgJ2Nocm9vdCttZW1vcnk6
Ly8vcGF0aC9CJywgY2hyb290PSdtZW1vcnk6Ly8vcGF0aC8nKQorICAgICAgICBzZWxmLmFzc2Vy
dEVxdWFsKCdtZW1vcnk6Ly8vcGF0aC8nLCB0cmFuc3BvcnQuY2hyb290X3VybCkKKworICAgIGRl
ZiB0ZXN0X2FwcGVuZF9maWxlKHNlbGYpOgorICAgICAgICB0cmFuc3BvcnQgPSBnZXRfdHJhbnNw
b3J0KCdjaHJvb3QrZmlsZTovLy9mb28vYmFyJykKKyAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMo
UGF0aE5vdENoaWxkLCB0cmFuc3BvcnQuYXBwZW5kX2ZpbGUsICcvZm9vJywgTm9uZSkKKworICAg
IGRlZiB0ZXN0X2FwcGVuZF9ieXRlcyhzZWxmKToKKyAgICAgICAgdHJhbnNwb3J0ID0gZ2V0X3Ry
YW5zcG9ydCgnY2hyb290K2ZpbGU6Ly8vZm9vL2JhcicpCisgICAgICAgIHNlbGYuYXNzZXJ0UmFp
c2VzKFBhdGhOb3RDaGlsZCwgdHJhbnNwb3J0LmFwcGVuZF9ieXRlcywgJy9mb28nLCAnYnl0ZXMn
KQorCisgICAgZGVmIHRlc3RfY2xvbmUoc2VsZik6CisgICAgICAgIHRyYW5zcG9ydCA9IGdldF90
cmFuc3BvcnQoJ2Nocm9vdCtmaWxlOi8vL2Zvby9iYXInKQorICAgICAgICBzZWxmLmFzc2VydFJh
aXNlcyhQYXRoTm90Q2hpbGQsIHRyYW5zcG9ydC5jbG9uZSwgJy9mb28nKQorCisgICAgZGVmIHRl
c3RfZGVsZXRlKHNlbGYpOgorICAgICAgICB0cmFuc3BvcnQgPSBnZXRfdHJhbnNwb3J0KCdjaHJv
b3QrZmlsZTovLy9mb28vYmFyJykKKyAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoUGF0aE5vdENo
aWxkLCB0cmFuc3BvcnQuZGVsZXRlLCAnL2ZvbycpCisKKyAgICBkZWYgdGVzdF9kZWxldGVfdHJl
ZShzZWxmKToKKyAgICAgICAgdHJhbnNwb3J0ID0gZ2V0X3RyYW5zcG9ydCgnY2hyb290K2ZpbGU6
Ly8vZm9vL2JhcicpCisgICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKFBhdGhOb3RDaGlsZCwgdHJh
bnNwb3J0LmRlbGV0ZV90cmVlLCAnL2ZvbycpCisKKyAgICBkZWYgdGVzdF9nZXQoc2VsZik6Cisg
ICAgICAgIHRyYW5zcG9ydCA9IGdldF90cmFuc3BvcnQoJ2Nocm9vdCtmaWxlOi8vL2Zvby9iYXIn
KQorICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhQYXRoTm90Q2hpbGQsIHRyYW5zcG9ydC5nZXQs
ICcvZm9vJykKKworICAgIGRlZiB0ZXN0X2dldF9ieXRlcyhzZWxmKToKKyAgICAgICAgdHJhbnNw
b3J0ID0gZ2V0X3RyYW5zcG9ydCgnY2hyb290K2ZpbGU6Ly8vZm9vL2JhcicpCisgICAgICAgIHNl
bGYuYXNzZXJ0UmFpc2VzKFBhdGhOb3RDaGlsZCwgdHJhbnNwb3J0LmdldF9ieXRlcywgJy9mb28n
KQorCisgICAgZGVmIHRlc3RfaGFzKHNlbGYpOgorICAgICAgICB0cmFuc3BvcnQgPSBnZXRfdHJh
bnNwb3J0KCdjaHJvb3QrZmlsZTovLy9mb28vYmFyJykKKyAgICAgICAgc2VsZi5hc3NlcnRSYWlz
ZXMoUGF0aE5vdENoaWxkLCB0cmFuc3BvcnQuaGFzLCAnL2ZvbycpCisKKyAgICBkZWYgdGVzdF9s
aXN0X2RpcihzZWxmKToKKyAgICAgICAgdHJhbnNwb3J0ID0gZ2V0X3RyYW5zcG9ydCgnY2hyb290
K2ZpbGU6Ly8vZm9vL2JhcicpCisgICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKFBhdGhOb3RDaGls
ZCwgdHJhbnNwb3J0Lmxpc3RfZGlyLCAnL2ZvbycpCisKKyAgICBkZWYgdGVzdF9sb2NrX3JlYWQo
c2VsZik6CisgICAgICAgIHRyYW5zcG9ydCA9IGdldF90cmFuc3BvcnQoJ2Nocm9vdCtmaWxlOi8v
L2Zvby9iYXInKQorICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhQYXRoTm90Q2hpbGQsIHRyYW5z
cG9ydC5sb2NrX3JlYWQsICcvZm9vJykKKworICAgIGRlZiB0ZXN0X2xvY2tfd3JpdGUoc2VsZik6
CisgICAgICAgIHRyYW5zcG9ydCA9IGdldF90cmFuc3BvcnQoJ2Nocm9vdCtmaWxlOi8vL2Zvby9i
YXInKQorICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhQYXRoTm90Q2hpbGQsIHRyYW5zcG9ydC5s
b2NrX3dyaXRlLCAnL2ZvbycpCisKKyAgICBkZWYgdGVzdF9ta2RpcihzZWxmKToKKyAgICAgICAg
dHJhbnNwb3J0ID0gZ2V0X3RyYW5zcG9ydCgnY2hyb290K2ZpbGU6Ly8vZm9vL2JhcicpCisgICAg
ICAgIHNlbGYuYXNzZXJ0UmFpc2VzKFBhdGhOb3RDaGlsZCwgdHJhbnNwb3J0Lm1rZGlyLCAnL2Zv
bycpCisKKyAgICBkZWYgdGVzdF9wdXRfYnl0ZXMoc2VsZik6CisgICAgICAgIHRyYW5zcG9ydCA9
IGdldF90cmFuc3BvcnQoJ2Nocm9vdCtmaWxlOi8vL2Zvby9iYXInKQorICAgICAgICBzZWxmLmFz
c2VydFJhaXNlcyhQYXRoTm90Q2hpbGQsIHRyYW5zcG9ydC5wdXRfYnl0ZXMsICcvZm9vJywgJ2J5
dGVzJykKKworICAgIGRlZiB0ZXN0X3B1dF9maWxlKHNlbGYpOgorICAgICAgICB0cmFuc3BvcnQg
PSBnZXRfdHJhbnNwb3J0KCdjaHJvb3QrZmlsZTovLy9mb28vYmFyJykKKyAgICAgICAgc2VsZi5h
c3NlcnRSYWlzZXMoUGF0aE5vdENoaWxkLCB0cmFuc3BvcnQucHV0X2ZpbGUsICcvZm9vJywgTm9u
ZSkKKworICAgIGRlZiB0ZXN0X3JlbmFtZShzZWxmKToKKyAgICAgICAgdHJhbnNwb3J0ID0gZ2V0
X3RyYW5zcG9ydCgnY2hyb290K2ZpbGU6Ly8vZm9vL2JhcicpCisgICAgICAgIHNlbGYuYXNzZXJ0
UmFpc2VzKFBhdGhOb3RDaGlsZCwgdHJhbnNwb3J0LnJlbmFtZSwgJy9hYWEnLCAnYmJiJykKKyAg
ICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoUGF0aE5vdENoaWxkLCB0cmFuc3BvcnQucmVuYW1lLCAn
Y2NjJywgJy9kJykKKworICAgIGRlZiB0ZXN0X3JtZGlyKHNlbGYpOgorICAgICAgICB0cmFuc3Bv
cnQgPSBnZXRfdHJhbnNwb3J0KCdjaHJvb3QrZmlsZTovLy9mb28vYmFyJykKKyAgICAgICAgc2Vs
Zi5hc3NlcnRSYWlzZXMoUGF0aE5vdENoaWxkLCB0cmFuc3BvcnQucm1kaXIsICcvZm9vJykKKwor
ICAgIGRlZiB0ZXN0X3N0YXQoc2VsZik6CisgICAgICAgIHRyYW5zcG9ydCA9IGdldF90cmFuc3Bv
cnQoJ2Nocm9vdCtmaWxlOi8vL2Zvby9iYXInKQorICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhQ
YXRoTm90Q2hpbGQsIHRyYW5zcG9ydC5zdGF0LCAnL2ZvbycpCisKICAgICAgICAgCiBjbGFzcyBS
ZWFkb25seURlY29yYXRvclRyYW5zcG9ydFRlc3QoVGVzdENhc2UpOgogICAgICIiIlJlYWRvbmx5
IGRlY29yYXRpb24gc3BlY2lmaWMgdGVzdHMuIiIiCgo=

=== modified file bzrlib/tests/test_transport_implementations.py // encoding:ba
... se64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydF9pbXBsZW1lbnRhdGlvbnMucHkKKysrIGJ6
cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydF9pbXBsZW1lbnRhdGlvbnMucHkKQEAgLTM4LDcgKzM4
LDcgQEAKIGZyb20gYnpybGliLnN5bWJvbF92ZXJzaW9uaW5nIGltcG9ydCB6ZXJvX2VsZXZlbgog
ZnJvbSBienJsaWIudGVzdHMgaW1wb3J0IFRlc3RDYXNlSW5UZW1wRGlyLCBUZXN0U2tpcHBlZAog
ZnJvbSBienJsaWIudGVzdHMudGVzdF90cmFuc3BvcnQgaW1wb3J0IFRlc3RUcmFuc3BvcnRJbXBs
ZW1lbnRhdGlvbgotZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCBtZW1vcnksIHNtYXJ0Citm
cm9tIGJ6cmxpYi50cmFuc3BvcnQgaW1wb3J0IG1lbW9yeSwgc21hcnQsIGNocm9vdAogaW1wb3J0
IGJ6cmxpYi50cmFuc3BvcnQKIAogCkBAIC05NCw3ICs5NCw4IEBACiAKICAgICBkZWYgdGVzdF9o
YXNfcm9vdF93b3JrcyhzZWxmKToKICAgICAgICAgY3VycmVudF90cmFuc3BvcnQgPSBzZWxmLmdl
dF90cmFuc3BvcnQoKQotICAgICAgICAjIGltcG9ydCBwZGI7cGRiLnNldF90cmFjZSgpCisgICAg
ICAgIGlmIGlzaW5zdGFuY2UoY3VycmVudF90cmFuc3BvcnQsIGNocm9vdC5DaHJvb3RUcmFuc3Bv
cnREZWNvcmF0b3IpOgorICAgICAgICAgICAgcmFpc2UgVGVzdFNraXBwZWQoIkNocm9vdFRyYW5z
cG9ydERlY29yYXRvciBkaXNhbGxvd3MgY2xvbmUoJy4uJykiKQogICAgICAgICBzZWxmLmFzc2Vy
dFRydWUoY3VycmVudF90cmFuc3BvcnQuaGFzKCcvJykpCiAgICAgICAgIHJvb3QgPSBjdXJyZW50
X3RyYW5zcG9ydC5jbG9uZSgnLycpCiAgICAgICAgIHNlbGYuYXNzZXJ0VHJ1ZShyb290Lmhhcygn
JykpCkBAIC0xMDEyLDYgKzEwMTMsOCBAQAogICAgIGRlZiB0ZXN0X2Nsb25lKHNlbGYpOgogICAg
ICAgICAjIFRPRE86IFRlc3QgdGhhdCBjbG9uZSBtb3ZlcyB1cCBhbmQgZG93biB0aGUgZmlsZXN5
c3RlbQogICAgICAgICB0MSA9IHNlbGYuZ2V0X3RyYW5zcG9ydCgpCisgICAgICAgIGlmIGlzaW5z
dGFuY2UodDEsIGNocm9vdC5DaHJvb3RUcmFuc3BvcnREZWNvcmF0b3IpOgorICAgICAgICAgICAg
cmFpc2UgVGVzdFNraXBwZWQoIkNocm9vdFRyYW5zcG9ydERlY29yYXRvciBkaXNhbGxvd3MgY2xv
bmUoJy4uJykiKQogCiAgICAgICAgIHNlbGYuYnVpbGRfdHJlZShbJ2EnLCAnYi8nLCAnYi9jJ10s
IHRyYW5zcG9ydD10MSkKIApAQCAtMTA0NCw2ICsxMDQ3LDggQEAKIAogICAgIGRlZiB0ZXN0X2Ns
b25lX3RvX3Jvb3Qoc2VsZik6CiAgICAgICAgIG9yaWdfdHJhbnNwb3J0ID0gc2VsZi5nZXRfdHJh
bnNwb3J0KCkKKyAgICAgICAgaWYgaXNpbnN0YW5jZShvcmlnX3RyYW5zcG9ydCwgY2hyb290LkNo
cm9vdFRyYW5zcG9ydERlY29yYXRvcik6CisgICAgICAgICAgICByYWlzZSBUZXN0U2tpcHBlZCgi
Q2hyb290VHJhbnNwb3J0RGVjb3JhdG9yIGRpc2FsbG93cyBjbG9uZSgnLi4nKSIpCiAgICAgICAg
ICMgUmVwZWF0ZWRseSBnbyB1cCB0byBhIHBhcmVudCBkaXJlY3RvcnkgdW50aWwgd2UncmUgYXQg
dGhlIHJvb3QKICAgICAgICAgIyBkaXJlY3Rvcnkgb2YgdGhpcyB0cmFuc3BvcnQKICAgICAgICAg
cm9vdF90cmFuc3BvcnQgPSBvcmlnX3RyYW5zcG9ydApAQCAtMTA3Miw2ICsxMDc3LDggQEAKICAg
ICBkZWYgdGVzdF9jbG9uZV9mcm9tX3Jvb3Qoc2VsZik6CiAgICAgICAgICIiIkF0IHRoZSByb290
LCBjbG9uaW5nIHRvIGEgc2ltcGxlIGRpciBzaG91bGQganVzdCBkbyBzdHJpbmcgYXBwZW5kLiIi
IgogICAgICAgICBvcmlnX3RyYW5zcG9ydCA9IHNlbGYuZ2V0X3RyYW5zcG9ydCgpCisgICAgICAg
IGlmIGlzaW5zdGFuY2Uob3JpZ190cmFuc3BvcnQsIGNocm9vdC5DaHJvb3RUcmFuc3BvcnREZWNv
cmF0b3IpOgorICAgICAgICAgICAgcmFpc2UgVGVzdFNraXBwZWQoIkNocm9vdFRyYW5zcG9ydERl
Y29yYXRvciBkaXNhbGxvd3MgY2xvbmUoJy8nKSIpCiAgICAgICAgIHJvb3RfdHJhbnNwb3J0ID0g
b3JpZ190cmFuc3BvcnQuY2xvbmUoJy8nKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHJvb3Rf
dHJhbnNwb3J0LmJhc2UgKyAnLmJ6ci8nLAogICAgICAgICAgICAgcm9vdF90cmFuc3BvcnQuY2xv
bmUoJy5ienInKS5iYXNlKQpAQCAtMTA5Miw2ICsxMDk5LDggQEAKIAogICAgIGRlZiB0ZXN0X3Jl
bHBhdGhfYXRfcm9vdChzZWxmKToKICAgICAgICAgdCA9IHNlbGYuZ2V0X3RyYW5zcG9ydCgpCisg
ICAgICAgIGlmIGlzaW5zdGFuY2UodCwgY2hyb290LkNocm9vdFRyYW5zcG9ydERlY29yYXRvcik6
CisgICAgICAgICAgICByYWlzZSBUZXN0U2tpcHBlZCgiQ2hyb290VHJhbnNwb3J0RGVjb3JhdG9y
IGRpc2FsbG93cyBjbG9uZSgnLi4nKSIpCiAgICAgICAgICMgY2xvbmUgYWxsIHRoZSB3YXkgdG8g
dGhlIHRvcAogICAgICAgICBuZXdfdHJhbnNwb3J0ID0gdC5jbG9uZSgnLi4nKQogICAgICAgICB3
aGlsZSBuZXdfdHJhbnNwb3J0LmJhc2UgIT0gdC5iYXNlOgpAQCAtMTEyOCw2ICsxMTM3LDggQEAK
IAogICAgIGRlZiB0ZXN0X2Fic3BhdGhfYXRfcm9vdChzZWxmKToKICAgICAgICAgdCA9IHNlbGYu
Z2V0X3RyYW5zcG9ydCgpCisgICAgICAgIGlmIGlzaW5zdGFuY2UodCwgY2hyb290LkNocm9vdFRy
YW5zcG9ydERlY29yYXRvcik6CisgICAgICAgICAgICByYWlzZSBUZXN0U2tpcHBlZCgiQ2hyb290
VHJhbnNwb3J0RGVjb3JhdG9yIGRpc2FsbG93cyBjbG9uZSgnLi4nKSIpCiAgICAgICAgICMgY2xv
bmUgYWxsIHRoZSB3YXkgdG8gdGhlIHRvcAogICAgICAgICBuZXdfdHJhbnNwb3J0ID0gdC5jbG9u
ZSgnLi4nKQogICAgICAgICB3aGlsZSBuZXdfdHJhbnNwb3J0LmJhc2UgIT0gdC5iYXNlOgpAQCAt
MTIzMiw2ICsxMjQzLDggQEAKICAgICAgICAgIyBjaGVjayB0aGF0IG91ciBzZXJ2ZXIgKHdoYXRl
dmVyIGl0IGlzKSBpcyBhY2Nlc3NhYmxlIHJlbGlhYmx5CiAgICAgICAgICMgdmlhIGdldF90cmFu
c3BvcnQgYW5kIG11bHRpcGxlIGNvbm5lY3Rpb25zIHNoYXJlIGNvbnRlbnQuCiAgICAgICAgIHRy
YW5zcG9ydCA9IHNlbGYuZ2V0X3RyYW5zcG9ydCgpCisgICAgICAgIGlmIGlzaW5zdGFuY2UodHJh
bnNwb3J0LCBjaHJvb3QuQ2hyb290VHJhbnNwb3J0RGVjb3JhdG9yKToKKyAgICAgICAgICAgIHJh
aXNlIFRlc3RTa2lwcGVkKCJDaHJvb3RUcmFuc3BvcnREZWNvcmF0b3IgZGlzYWxsb3dzIGNsb25l
KCcuLicpIikKICAgICAgICAgaWYgdHJhbnNwb3J0LmlzX3JlYWRvbmx5KCk6CiAgICAgICAgICAg
ICByZXR1cm4KICAgICAgICAgdHJhbnNwb3J0LnB1dF9ieXRlcygnZm9vJywgJ2JhcicpCgo=

=== modified file bzrlib/transport/__init__.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvX19pbml0X18ucHkKKysrIGJ6cmxpYi90cmFuc3BvcnQvX19p
bml0X18ucHkKQEAgLTExNjQsNiArMTE2NCw4IEBACiByZWdpc3Rlcl9sYXp5X3RyYW5zcG9ydCgn
ZnRwOi8vJywgJ2J6cmxpYi50cmFuc3BvcnQuZnRwJywgJ0Z0cFRyYW5zcG9ydCcpCiByZWdpc3Rl
cl9sYXp5X3RyYW5zcG9ydCgnYWZ0cDovLycsICdienJsaWIudHJhbnNwb3J0LmZ0cCcsICdGdHBU
cmFuc3BvcnQnKQogcmVnaXN0ZXJfbGF6eV90cmFuc3BvcnQoJ21lbW9yeTovLycsICdienJsaWIu
dHJhbnNwb3J0Lm1lbW9yeScsICdNZW1vcnlUcmFuc3BvcnQnKQorcmVnaXN0ZXJfbGF6eV90cmFu
c3BvcnQoJ2Nocm9vdCsnLCAnYnpybGliLnRyYW5zcG9ydC5jaHJvb3QnLAorICAgICAgICAgICAg
ICAgICAgICAgICAgJ0Nocm9vdFRyYW5zcG9ydERlY29yYXRvcicpCiByZWdpc3Rlcl9sYXp5X3Ry
YW5zcG9ydCgncmVhZG9ubHkrJywgJ2J6cmxpYi50cmFuc3BvcnQucmVhZG9ubHknLCAnUmVhZG9u
bHlUcmFuc3BvcnREZWNvcmF0b3InKQogcmVnaXN0ZXJfbGF6eV90cmFuc3BvcnQoJ2Zha2VuZnMr
JywgJ2J6cmxpYi50cmFuc3BvcnQuZmFrZW5mcycsICdGYWtlTkZTVHJhbnNwb3J0RGVjb3JhdG9y
JykKIHJlZ2lzdGVyX2xhenlfdHJhbnNwb3J0KCd2ZmF0KycsCgo=

# revision id: andrew.bennetts at canonical.com-20061012060928-e387650ef98b70f5
# sha1: f2004de424458d7318345229f244e09f66defab5
# inventory sha1: d4d20ed79c50f03e799e6e46d7708a3c593271d1
# parent ids:
#   pqm at pqm.ubuntu.com-20061010072307-037a6f63da8a1bdd
# properties:
#   branch-nick: chroot decorator



More information about the bazaar mailing list