[MERGE] Fix handling of unicode paths in smart server requests

Andrew Bennetts andrew at canonical.com
Thu Oct 12 11:49:04 BST 2006


http://people.ubuntu.com/~andrew/bzr/smart-server-unicode/ contains tests and
fixes for handling of unicode paths in smart server requests.  There's some
double-handling (UTF-8 read off the wire gets decoded, then re-encoded), but at
least it's correct.

I haven't tested handling of non-ascii paths in responses yet, so I assume they
are broken!  I'll take a look and add tests and if necessary fixes soon, but
this branch is already useful as is.

The branch is against http://people.ubuntu.com/~andrew/bzr/http-smart-server/,
because it builds on the refactoring that occurred in that branch.

I've attached a bundle relative to that branch for review.

-Andrew.

-------------- next part --------------
# Bazaar revision bundle v0.8
#
# message:
#   Add a NEWS entry for this fix.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-10-12 18:59:43.742000103 +1000

=== modified file NEWS
--- NEWS
+++ NEWS
@@ -39,6 +39,9 @@
 
    * diff3 does not indicate conflicts on clean merge. (Aaron Bentley)
 
+    * The smart server now dispatches commands with non-ascii paths correctly.
+      (Andrew Bennetts)
+
   TESTING:
 
     * New test base class TestCaseWithMemoryTransport offers memory-only

=== modified file bzrlib/tests/test_smart_transport.py // last-changed:andrew.b
... ennetts at canonical.com-20061012085801-36b60463388ea0e7
--- bzrlib/tests/test_smart_transport.py
+++ bzrlib/tests/test_smart_transport.py
@@ -596,7 +596,7 @@
         self.assertEqual('ok\0011\n',
                          from_server.getvalue())
 
-    def test_canned_get_response(self):
+    def test_response_to_canned_get(self):
         transport = memory.MemoryTransport('memory:///')
         transport.put_bytes('testfile', 'contents\nof\nfile\n')
         to_server = StringIO('get\001./testfile\n')
@@ -612,6 +612,24 @@
                          'done\n',
                          from_server.getvalue())
 
+    def test_response_to_canned_get_of_utf8(self):
+        # wire-to-wire, using the whole stack, with a UTF-8 filename.
+        transport = memory.MemoryTransport('memory:///')
+        utf8_filename = u'testfile\N{INTERROBANG}'.encode('utf-8')
+        transport.put_bytes(utf8_filename, 'contents\nof\nfile\n')
+        to_server = StringIO('get\001' + utf8_filename + '\n')
+        from_server = StringIO()
+        server = smart.SmartServerPipeStreamMedium(
+            to_server, from_server, transport)
+        protocol = smart.SmartServerRequestProtocolOne(transport,
+                from_server.write)
+        server._serve_one_request(protocol)
+        self.assertEqual('ok\n'
+                         '17\n'
+                         'contents\nof\nfile\n'
+                         'done\n',
+                         from_server.getvalue())
+
     def test_pipe_like_stream_with_bulk_data(self):
         sample_request_bytes = 'command\n9\nbulk datadone\n'
         to_server = StringIO(sample_request_bytes)
@@ -933,7 +951,7 @@
     def test_put_bytes_non_atomic(self):
         """'put_...' should set finished_reading after reading the bytes."""
         handler = smart.SmartServerRequestHandler(self.get_transport())
-        handler.dispatch_command('put_non_atomic', ('a-file', '', 'F', ''))
+        handler.dispatch_command('put_non_atomic', (u'a-file', u'', u'F', u''))
         self.assertFalse(handler.finished_reading)
         handler.accept_body('1234')
         self.assertFalse(handler.finished_reading)
@@ -947,7 +965,7 @@
         """'readv' should set finished_reading after reading offsets."""
         self.build_tree(['a-file'])
         handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
-        handler.dispatch_command('readv', ('a-file', ))
+        handler.dispatch_command('readv', (u'a-file', ))
         self.assertFalse(handler.finished_reading)
         handler.accept_body('2,')
         self.assertFalse(handler.finished_reading)
@@ -962,7 +980,7 @@
         """'readv' when a short read occurs sets the response appropriately."""
         self.build_tree(['a-file'])
         handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
-        handler.dispatch_command('readv', ('a-file', ))
+        handler.dispatch_command('readv', (u'a-file', ))
         # read beyond the end of the file.
         handler.accept_body('100,1')
         handler.end_of_body()
@@ -972,6 +990,132 @@
         self.assertEqual(None, handler.response.body)
 
 
+class SmartServerRequestHandlerUnicodeTests(tests.TestCaseWithTransport):
+    """Test unicode relpaths passed to the request handler.
+
+    SmartServerRequestProtocolOne decodes requests into a tuple of unicode
+    objects.  That tuple is then passed to the request handler's
+    dispatch_command method.  This test case is for testing that unicode paths
+    are handled correctly by the request handler.
+    """
+
+    def test_get_file(self):
+        self.build_tree([u'\N{INTERROBANG}'], line_endings='binary')
+        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler.dispatch_command('get', (u'\N{INTERROBANG}',))
+        self.assertEqual(('ok',), handler.response.args)
+        self.assertEqual(
+            u'contents of \N{INTERROBANG}\n'.encode('utf-8'),
+            handler.response.body)
+
+    def test_has(self):
+        self.build_tree([u'\N{INTERROBANG}'])
+        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler.dispatch_command('has', (u'\N{INTERROBANG}',))
+        self.assertEqual(('yes',), handler.response.args)
+
+    def test_append(self):
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command('append', (u'\N{INTERROBANG}', ''))
+        handler.accept_body('abc\n')
+        handler.end_of_body()
+        self.assertEqual(('appended', '0'), handler.response.args)
+        self.check_file_contents(u'\N{INTERROBANG}'.encode('utf-8'), 'abc\n')
+
+    def test_delete(self):
+        self.build_tree([u'\N{INTERROBANG}'])
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command('delete', (u'\N{INTERROBANG}',))
+        self.assertEqual(('ok',), handler.response.args)
+        self.failIfExists(u'\N{INTERROBANG}'.encode('utf-8'))
+
+    def test_iter_files_recursive(self):
+        self.build_tree([
+            u'\N{INTERROBANG}/',
+            u'\N{INTERROBANG}/one',
+            u'\N{INTERROBANG}/two',
+            ])
+        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler.dispatch_command('iter_files_recursive', (u'\N{INTERROBANG}',))
+        self.assertEqual('names', handler.response.args[0])
+        self.assertEqual(set(['one', 'two']), set(handler.response.args[1:]))
+
+    def test_list_dir(self):
+        self.build_tree([
+            u'\N{INTERROBANG}/',
+            u'\N{INTERROBANG}/one',
+            u'\N{INTERROBANG}/two',
+            ])
+        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler.dispatch_command('list_dir', (u'\N{INTERROBANG}',))
+        self.assertEqual('names', handler.response.args[0])
+        self.assertEqual(set(['one', 'two']), set(handler.response.args[1:]))
+
+    def test_mkdir(self):
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command('mkdir', (u'\N{INTERROBANG}', ''))
+        self.assertEqual(('ok',), handler.response.args)
+        self.failUnlessExists(u'\N{INTERROBANG}'.encode('utf-8'))
+
+    def test_move(self):
+        self.build_tree([u'one\N{INTERROBANG}'])
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command(
+            'move', (u'one\N{INTERROBANG}', u'two\N{INTERROBANG}',))
+        self.assertEqual(('ok',), handler.response.args)
+        self.failIfExists(u'one\N{INTERROBANG}'.encode('utf-8'))
+        self.failUnlessExists(u'two\N{INTERROBANG}'.encode('utf-8'))
+
+    def test_put(self):
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command('put', (u'\N{INTERROBANG}', ''))
+        handler.accept_body('abc\n')
+        handler.end_of_body()
+        self.assertEqual(('ok',), handler.response.args)
+        self.check_file_contents(u'\N{INTERROBANG}'.encode('utf-8'), 'abc\n')
+
+    def test_put_non_atomic(self):
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command(
+            'put_non_atomic', (u'\N{INTERROBANG}', '', 'F', ''))
+        handler.accept_body('abc\n')
+        handler.end_of_body()
+        self.assertEqual(('ok',), handler.response.args)
+        self.check_file_contents(u'\N{INTERROBANG}'.encode('utf-8'), 'abc\n')
+
+    def test_readv(self):
+        self.build_tree([u'\N{INTERROBANG}'])
+        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler.dispatch_command('readv', (u'\N{INTERROBANG}',))
+        handler.accept_body('2,3')
+        handler.end_of_body()
+        self.assertEqual(('readv', ), handler.response.args)
+        # co - nte - nt of a-file is the file contents we are extracting from.
+        self.assertEqual('nte', handler.response.body)
+
+    def test_rename(self):
+        self.build_tree([u'one\N{INTERROBANG}'])
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command(
+            'rename', (u'one\N{INTERROBANG}', u'two\N{INTERROBANG}',))
+        self.assertEqual(('ok',), handler.response.args)
+        self.failIfExists(u'one\N{INTERROBANG}'.encode('utf-8'))
+        self.failUnlessExists(u'two\N{INTERROBANG}'.encode('utf-8'))
+
+    def test_rmdir(self):
+        self.build_tree([u'\N{INTERROBANG}/'])
+        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler.dispatch_command('rmdir', (u'\N{INTERROBANG}',))
+        self.assertEqual(('ok',), handler.response.args)
+        self.failIfExists(u'\N{INTERROBANG}'.encode('utf-8'))
+
+    def test_stat(self):
+        self.build_tree([u'\N{INTERROBANG}'])
+        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler.dispatch_command('stat', (u'\N{INTERROBANG}',))
+        self.assertEqual('stat', handler.response.args[0])
+
+
 class SmartTransportRegistration(tests.TestCase):
 
     def test_registration(self):

=== modified file bzrlib/transport/smart.py // last-changed:andrew.bennetts at can
... onical.com-20061012085801-36b60463388ea0e7
--- bzrlib/transport/smart.py
+++ bzrlib/transport/smart.py
@@ -560,6 +560,7 @@
                 return
             bytes = self._in.read(bytes_to_read)
             if bytes == '':
+
                 # Connection has been closed.
                 self.finished = True
                 self._out.flush()
@@ -635,10 +636,12 @@
         return SmartServerResponse(('ok', '1'))
 
     def do_has(self, relpath):
+        relpath = relpath.encode('utf-8')
         r = self._backing_transport.has(relpath) and 'yes' or 'no'
         return SmartServerResponse((r,))
 
     def do_get(self, relpath):
+        relpath = relpath.encode('utf-8')
         backing_bytes = self._backing_transport.get_bytes(relpath)
         return SmartServerResponse(('ok',), backing_bytes)
 
@@ -651,7 +654,7 @@
 
     def do_append(self, relpath, mode):
         self._converted_command = True
-        self._relpath = relpath
+        self._relpath = relpath.encode('utf-8')
         self._mode = self._deserialise_optional_mode(mode)
         self._end_of_body_handler = self._handle_do_append_end
     
@@ -661,29 +664,33 @@
         self.response = SmartServerResponse(('appended', '%d' % old_length))
 
     def do_delete(self, relpath):
+        relpath = relpath.encode('utf-8')
         self._backing_transport.delete(relpath)
 
-    def do_iter_files_recursive(self, abspath):
-        # XXX: the path handling needs some thought.
-        #relpath = self._backing_transport.relpath(abspath)
-        transport = self._backing_transport.clone(abspath)
+    def do_iter_files_recursive(self, relpath):
+        relpath = relpath.encode('utf-8')
+        transport = self._backing_transport.clone(relpath)
         filenames = transport.iter_files_recursive()
         return SmartServerResponse(('names',) + tuple(filenames))
 
     def do_list_dir(self, relpath):
+        relpath = relpath.encode('utf-8')
         filenames = self._backing_transport.list_dir(relpath)
         return SmartServerResponse(('names',) + tuple(filenames))
 
     def do_mkdir(self, relpath, mode):
+        relpath = relpath.encode('utf-8')
         self._backing_transport.mkdir(relpath,
                                       self._deserialise_optional_mode(mode))
 
     def do_move(self, rel_from, rel_to):
+        rel_from = rel_from.encode('utf-8')
+        rel_to = rel_to.encode('utf-8')
         self._backing_transport.move(rel_from, rel_to)
 
     def do_put(self, relpath, mode):
         self._converted_command = True
-        self._relpath = relpath
+        self._relpath = relpath.encode('utf-8')
         self._mode = self._deserialise_optional_mode(mode)
         self._end_of_body_handler = self._handle_do_put
 
@@ -705,7 +712,7 @@
     def do_put_non_atomic(self, relpath, mode, create_parent, dir_mode):
         self._converted_command = True
         self._end_of_body_handler = self._handle_put_non_atomic
-        self._relpath = relpath
+        self._relpath = relpath.encode('utf-8')
         self._dir_mode = self._deserialise_optional_mode(dir_mode)
         self._mode = self._deserialise_optional_mode(mode)
         # a boolean would be nicer XXX
@@ -722,7 +729,7 @@
     def do_readv(self, relpath):
         self._converted_command = True
         self._end_of_body_handler = self._handle_readv_offsets
-        self._relpath = relpath
+        self._relpath = relpath.encode('utf-8')
 
     def end_of_body(self):
         """No more body data will be received."""
@@ -738,12 +745,16 @@
         self.response = SmartServerResponse(('readv',), backing_bytes)
         
     def do_rename(self, rel_from, rel_to):
+        rel_from = rel_from.encode('utf-8')
+        rel_to = rel_to.encode('utf-8')
         self._backing_transport.rename(rel_from, rel_to)
 
     def do_rmdir(self, relpath):
+        relpath = relpath.encode('utf-8')
         self._backing_transport.rmdir(relpath)
 
     def do_stat(self, relpath):
+        relpath = relpath.encode('utf-8')
         stat = self._backing_transport.stat(relpath)
         return SmartServerResponse(('stat', str(stat.st_size), oct(stat.st_mode)))
         

# revision id: andrew.bennetts at canonical.com-20061012085943-220c54b5ae219365
# sha1: cc4875699d70f6688c7985c4038edf74e828a797
# inventory sha1: 91bed157d023d03ae4946d8e9baf125c448d71a7
# parent ids:
#   andrew.bennetts at canonical.com-20061012085801-36b60463388ea0e7
# base id: andrew.bennetts at canonical.com-20061012063051-5efaeb5409f0dbad
# properties:
#   branch-nick: smart server unicode

# message:
#   Fix dispatching of smart server requests involving unicode paths.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Thu 2006-10-12 18:58:01.677000046 +1000

=== modified file bzrlib/tests/test_smart_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NtYXJ0X3RyYW5zcG9ydC5weQorKysgYnpybGliL3Rlc3Rz
L3Rlc3Rfc21hcnRfdHJhbnNwb3J0LnB5CkBAIC01OTYsNyArNTk2LDcgQEAKICAgICAgICAgc2Vs
Zi5hc3NlcnRFcXVhbCgnb2tcMDAxMVxuJywKICAgICAgICAgICAgICAgICAgICAgICAgICBmcm9t
X3NlcnZlci5nZXR2YWx1ZSgpKQogCi0gICAgZGVmIHRlc3RfY2FubmVkX2dldF9yZXNwb25zZShz
ZWxmKToKKyAgICBkZWYgdGVzdF9yZXNwb25zZV90b19jYW5uZWRfZ2V0KHNlbGYpOgogICAgICAg
ICB0cmFuc3BvcnQgPSBtZW1vcnkuTWVtb3J5VHJhbnNwb3J0KCdtZW1vcnk6Ly8vJykKICAgICAg
ICAgdHJhbnNwb3J0LnB1dF9ieXRlcygndGVzdGZpbGUnLCAnY29udGVudHNcbm9mXG5maWxlXG4n
KQogICAgICAgICB0b19zZXJ2ZXIgPSBTdHJpbmdJTygnZ2V0XDAwMS4vdGVzdGZpbGVcbicpCkBA
IC02MTIsNiArNjEyLDI0IEBACiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2RvbmVcbicsCiAg
ICAgICAgICAgICAgICAgICAgICAgICAgZnJvbV9zZXJ2ZXIuZ2V0dmFsdWUoKSkKIAorICAgIGRl
ZiB0ZXN0X3Jlc3BvbnNlX3RvX2Nhbm5lZF9nZXRfb2ZfdXRmOChzZWxmKToKKyAgICAgICAgIyB3
aXJlLXRvLXdpcmUsIHVzaW5nIHRoZSB3aG9sZSBzdGFjaywgd2l0aCBhIFVURi04IGZpbGVuYW1l
LgorICAgICAgICB0cmFuc3BvcnQgPSBtZW1vcnkuTWVtb3J5VHJhbnNwb3J0KCdtZW1vcnk6Ly8v
JykKKyAgICAgICAgdXRmOF9maWxlbmFtZSA9IHUndGVzdGZpbGVcTntJTlRFUlJPQkFOR30nLmVu
Y29kZSgndXRmLTgnKQorICAgICAgICB0cmFuc3BvcnQucHV0X2J5dGVzKHV0ZjhfZmlsZW5hbWUs
ICdjb250ZW50c1xub2ZcbmZpbGVcbicpCisgICAgICAgIHRvX3NlcnZlciA9IFN0cmluZ0lPKCdn
ZXRcMDAxJyArIHV0ZjhfZmlsZW5hbWUgKyAnXG4nKQorICAgICAgICBmcm9tX3NlcnZlciA9IFN0
cmluZ0lPKCkKKyAgICAgICAgc2VydmVyID0gc21hcnQuU21hcnRTZXJ2ZXJQaXBlU3RyZWFtTWVk
aXVtKAorICAgICAgICAgICAgdG9fc2VydmVyLCBmcm9tX3NlcnZlciwgdHJhbnNwb3J0KQorICAg
ICAgICBwcm90b2NvbCA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdFByb3RvY29sT25lKHRyYW5z
cG9ydCwKKyAgICAgICAgICAgICAgICBmcm9tX3NlcnZlci53cml0ZSkKKyAgICAgICAgc2VydmVy
Ll9zZXJ2ZV9vbmVfcmVxdWVzdChwcm90b2NvbCkKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgn
b2tcbicKKyAgICAgICAgICAgICAgICAgICAgICAgICAnMTdcbicKKyAgICAgICAgICAgICAgICAg
ICAgICAgICAnY29udGVudHNcbm9mXG5maWxlXG4nCisgICAgICAgICAgICAgICAgICAgICAgICAg
J2RvbmVcbicsCisgICAgICAgICAgICAgICAgICAgICAgICAgZnJvbV9zZXJ2ZXIuZ2V0dmFsdWUo
KSkKKwogICAgIGRlZiB0ZXN0X3BpcGVfbGlrZV9zdHJlYW1fd2l0aF9idWxrX2RhdGEoc2VsZik6
CiAgICAgICAgIHNhbXBsZV9yZXF1ZXN0X2J5dGVzID0gJ2NvbW1hbmRcbjlcbmJ1bGsgZGF0YWRv
bmVcbicKICAgICAgICAgdG9fc2VydmVyID0gU3RyaW5nSU8oc2FtcGxlX3JlcXVlc3RfYnl0ZXMp
CkBAIC05MzMsNyArOTUxLDcgQEAKICAgICBkZWYgdGVzdF9wdXRfYnl0ZXNfbm9uX2F0b21pYyhz
ZWxmKToKICAgICAgICAgIiIiJ3B1dF8uLi4nIHNob3VsZCBzZXQgZmluaXNoZWRfcmVhZGluZyBh
ZnRlciByZWFkaW5nIHRoZSBieXRlcy4iIiIKICAgICAgICAgaGFuZGxlciA9IHNtYXJ0LlNtYXJ0
U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfdHJhbnNwb3J0KCkpCi0gICAgICAgIGhhbmRs
ZXIuZGlzcGF0Y2hfY29tbWFuZCgncHV0X25vbl9hdG9taWMnLCAoJ2EtZmlsZScsICcnLCAnRics
ICcnKSkKKyAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdwdXRfbm9uX2F0b21pYycs
ICh1J2EtZmlsZScsIHUnJywgdSdGJywgdScnKSkKICAgICAgICAgc2VsZi5hc3NlcnRGYWxzZSho
YW5kbGVyLmZpbmlzaGVkX3JlYWRpbmcpCiAgICAgICAgIGhhbmRsZXIuYWNjZXB0X2JvZHkoJzEy
MzQnKQogICAgICAgICBzZWxmLmFzc2VydEZhbHNlKGhhbmRsZXIuZmluaXNoZWRfcmVhZGluZykK
QEAgLTk0Nyw3ICs5NjUsNyBAQAogICAgICAgICAiIiIncmVhZHYnIHNob3VsZCBzZXQgZmluaXNo
ZWRfcmVhZGluZyBhZnRlciByZWFkaW5nIG9mZnNldHMuIiIiCiAgICAgICAgIHNlbGYuYnVpbGRf
dHJlZShbJ2EtZmlsZSddKQogICAgICAgICBoYW5kbGVyID0gc21hcnQuU21hcnRTZXJ2ZXJSZXF1
ZXN0SGFuZGxlcihzZWxmLmdldF9yZWFkb25seV90cmFuc3BvcnQoKSkKLSAgICAgICAgaGFuZGxl
ci5kaXNwYXRjaF9jb21tYW5kKCdyZWFkdicsICgnYS1maWxlJywgKSkKKyAgICAgICAgaGFuZGxl
ci5kaXNwYXRjaF9jb21tYW5kKCdyZWFkdicsICh1J2EtZmlsZScsICkpCiAgICAgICAgIHNlbGYu
YXNzZXJ0RmFsc2UoaGFuZGxlci5maW5pc2hlZF9yZWFkaW5nKQogICAgICAgICBoYW5kbGVyLmFj
Y2VwdF9ib2R5KCcyLCcpCiAgICAgICAgIHNlbGYuYXNzZXJ0RmFsc2UoaGFuZGxlci5maW5pc2hl
ZF9yZWFkaW5nKQpAQCAtOTYyLDcgKzk4MCw3IEBACiAgICAgICAgICIiIidyZWFkdicgd2hlbiBh
IHNob3J0IHJlYWQgb2NjdXJzIHNldHMgdGhlIHJlc3BvbnNlIGFwcHJvcHJpYXRlbHkuIiIiCiAg
ICAgICAgIHNlbGYuYnVpbGRfdHJlZShbJ2EtZmlsZSddKQogICAgICAgICBoYW5kbGVyID0gc21h
cnQuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihzZWxmLmdldF9yZWFkb25seV90cmFuc3BvcnQo
KSkKLSAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdyZWFkdicsICgnYS1maWxlJywg
KSkKKyAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdyZWFkdicsICh1J2EtZmlsZScs
ICkpCiAgICAgICAgICMgcmVhZCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgZmlsZS4KICAgICAgICAg
aGFuZGxlci5hY2NlcHRfYm9keSgnMTAwLDEnKQogICAgICAgICBoYW5kbGVyLmVuZF9vZl9ib2R5
KCkKQEAgLTk3Miw2ICs5OTAsMTMyIEBACiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoTm9uZSwg
aGFuZGxlci5yZXNwb25zZS5ib2R5KQogCiAKK2NsYXNzIFNtYXJ0U2VydmVyUmVxdWVzdEhhbmRs
ZXJVbmljb2RlVGVzdHModGVzdHMuVGVzdENhc2VXaXRoVHJhbnNwb3J0KToKKyAgICAiIiJUZXN0
IHVuaWNvZGUgcmVscGF0aHMgcGFzc2VkIHRvIHRoZSByZXF1ZXN0IGhhbmRsZXIuCisKKyAgICBT
bWFydFNlcnZlclJlcXVlc3RQcm90b2NvbE9uZSBkZWNvZGVzIHJlcXVlc3RzIGludG8gYSB0dXBs
ZSBvZiB1bmljb2RlCisgICAgb2JqZWN0cy4gIFRoYXQgdHVwbGUgaXMgdGhlbiBwYXNzZWQgdG8g
dGhlIHJlcXVlc3QgaGFuZGxlcidzCisgICAgZGlzcGF0Y2hfY29tbWFuZCBtZXRob2QuICBUaGlz
IHRlc3QgY2FzZSBpcyBmb3IgdGVzdGluZyB0aGF0IHVuaWNvZGUgcGF0aHMKKyAgICBhcmUgaGFu
ZGxlZCBjb3JyZWN0bHkgYnkgdGhlIHJlcXVlc3QgaGFuZGxlci4KKyAgICAiIiIKKworICAgIGRl
ZiB0ZXN0X2dldF9maWxlKHNlbGYpOgorICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoW3UnXE57SU5U
RVJST0JBTkd9J10sIGxpbmVfZW5kaW5ncz0nYmluYXJ5JykKKyAgICAgICAgaGFuZGxlciA9IHNt
YXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfcmVhZG9ubHlfdHJhbnNwb3J0
KCkpCisgICAgICAgIGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgnZ2V0JywgKHUnXE57SU5URVJS
T0JBTkd9JywpKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCgnb2snLCksIGhhbmRsZXIucmVz
cG9uc2UuYXJncykKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgKKyAgICAgICAgICAgIHUnY29u
dGVudHMgb2YgXE57SU5URVJST0JBTkd9XG4nLmVuY29kZSgndXRmLTgnKSwKKyAgICAgICAgICAg
IGhhbmRsZXIucmVzcG9uc2UuYm9keSkKKworICAgIGRlZiB0ZXN0X2hhcyhzZWxmKToKKyAgICAg
ICAgc2VsZi5idWlsZF90cmVlKFt1J1xOe0lOVEVSUk9CQU5HfSddKQorICAgICAgICBoYW5kbGVy
ID0gc21hcnQuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihzZWxmLmdldF9yZWFkb25seV90cmFu
c3BvcnQoKSkKKyAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdoYXMnLCAodSdcTntJ
TlRFUlJPQkFOR30nLCkpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoKCd5ZXMnLCksIGhhbmRs
ZXIucmVzcG9uc2UuYXJncykKKworICAgIGRlZiB0ZXN0X2FwcGVuZChzZWxmKToKKyAgICAgICAg
aGFuZGxlciA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfdHJhbnNw
b3J0KCkpCisgICAgICAgIGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgnYXBwZW5kJywgKHUnXE57
SU5URVJST0JBTkd9JywgJycpKQorICAgICAgICBoYW5kbGVyLmFjY2VwdF9ib2R5KCdhYmNcbicp
CisgICAgICAgIGhhbmRsZXIuZW5kX29mX2JvZHkoKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFs
KCgnYXBwZW5kZWQnLCAnMCcpLCBoYW5kbGVyLnJlc3BvbnNlLmFyZ3MpCisgICAgICAgIHNlbGYu
Y2hlY2tfZmlsZV9jb250ZW50cyh1J1xOe0lOVEVSUk9CQU5HfScuZW5jb2RlKCd1dGYtOCcpLCAn
YWJjXG4nKQorCisgICAgZGVmIHRlc3RfZGVsZXRlKHNlbGYpOgorICAgICAgICBzZWxmLmJ1aWxk
X3RyZWUoW3UnXE57SU5URVJST0JBTkd9J10pCisgICAgICAgIGhhbmRsZXIgPSBzbWFydC5TbWFy
dFNlcnZlclJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3RyYW5zcG9ydCgpKQorICAgICAgICBoYW5k
bGVyLmRpc3BhdGNoX2NvbW1hbmQoJ2RlbGV0ZScsICh1J1xOe0lOVEVSUk9CQU5HfScsKSkKKyAg
ICAgICAgc2VsZi5hc3NlcnRFcXVhbCgoJ29rJywpLCBoYW5kbGVyLnJlc3BvbnNlLmFyZ3MpCisg
ICAgICAgIHNlbGYuZmFpbElmRXhpc3RzKHUnXE57SU5URVJST0JBTkd9Jy5lbmNvZGUoJ3V0Zi04
JykpCisKKyAgICBkZWYgdGVzdF9pdGVyX2ZpbGVzX3JlY3Vyc2l2ZShzZWxmKToKKyAgICAgICAg
c2VsZi5idWlsZF90cmVlKFsKKyAgICAgICAgICAgIHUnXE57SU5URVJST0JBTkd9LycsCisgICAg
ICAgICAgICB1J1xOe0lOVEVSUk9CQU5HfS9vbmUnLAorICAgICAgICAgICAgdSdcTntJTlRFUlJP
QkFOR30vdHdvJywKKyAgICAgICAgICAgIF0pCisgICAgICAgIGhhbmRsZXIgPSBzbWFydC5TbWFy
dFNlcnZlclJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3JlYWRvbmx5X3RyYW5zcG9ydCgpKQorICAg
ICAgICBoYW5kbGVyLmRpc3BhdGNoX2NvbW1hbmQoJ2l0ZXJfZmlsZXNfcmVjdXJzaXZlJywgKHUn
XE57SU5URVJST0JBTkd9JywpKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCduYW1lcycsIGhh
bmRsZXIucmVzcG9uc2UuYXJnc1swXSkKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChzZXQoWydv
bmUnLCAndHdvJ10pLCBzZXQoaGFuZGxlci5yZXNwb25zZS5hcmdzWzE6XSkpCisKKyAgICBkZWYg
dGVzdF9saXN0X2RpcihzZWxmKToKKyAgICAgICAgc2VsZi5idWlsZF90cmVlKFsKKyAgICAgICAg
ICAgIHUnXE57SU5URVJST0JBTkd9LycsCisgICAgICAgICAgICB1J1xOe0lOVEVSUk9CQU5HfS9v
bmUnLAorICAgICAgICAgICAgdSdcTntJTlRFUlJPQkFOR30vdHdvJywKKyAgICAgICAgICAgIF0p
CisgICAgICAgIGhhbmRsZXIgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKHNlbGYu
Z2V0X3JlYWRvbmx5X3RyYW5zcG9ydCgpKQorICAgICAgICBoYW5kbGVyLmRpc3BhdGNoX2NvbW1h
bmQoJ2xpc3RfZGlyJywgKHUnXE57SU5URVJST0JBTkd9JywpKQorICAgICAgICBzZWxmLmFzc2Vy
dEVxdWFsKCduYW1lcycsIGhhbmRsZXIucmVzcG9uc2UuYXJnc1swXSkKKyAgICAgICAgc2VsZi5h
c3NlcnRFcXVhbChzZXQoWydvbmUnLCAndHdvJ10pLCBzZXQoaGFuZGxlci5yZXNwb25zZS5hcmdz
WzE6XSkpCisKKyAgICBkZWYgdGVzdF9ta2RpcihzZWxmKToKKyAgICAgICAgaGFuZGxlciA9IHNt
YXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfdHJhbnNwb3J0KCkpCisgICAg
ICAgIGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgnbWtkaXInLCAodSdcTntJTlRFUlJPQkFOR30n
LCAnJykpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoKCdvaycsKSwgaGFuZGxlci5yZXNwb25z
ZS5hcmdzKQorICAgICAgICBzZWxmLmZhaWxVbmxlc3NFeGlzdHModSdcTntJTlRFUlJPQkFOR30n
LmVuY29kZSgndXRmLTgnKSkKKworICAgIGRlZiB0ZXN0X21vdmUoc2VsZik6CisgICAgICAgIHNl
bGYuYnVpbGRfdHJlZShbdSdvbmVcTntJTlRFUlJPQkFOR30nXSkKKyAgICAgICAgaGFuZGxlciA9
IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfdHJhbnNwb3J0KCkpCisg
ICAgICAgIGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgKKyAgICAgICAgICAgICdtb3ZlJywgKHUn
b25lXE57SU5URVJST0JBTkd9JywgdSd0d29cTntJTlRFUlJPQkFOR30nLCkpCisgICAgICAgIHNl
bGYuYXNzZXJ0RXF1YWwoKCdvaycsKSwgaGFuZGxlci5yZXNwb25zZS5hcmdzKQorICAgICAgICBz
ZWxmLmZhaWxJZkV4aXN0cyh1J29uZVxOe0lOVEVSUk9CQU5HfScuZW5jb2RlKCd1dGYtOCcpKQor
ICAgICAgICBzZWxmLmZhaWxVbmxlc3NFeGlzdHModSd0d29cTntJTlRFUlJPQkFOR30nLmVuY29k
ZSgndXRmLTgnKSkKKworICAgIGRlZiB0ZXN0X3B1dChzZWxmKToKKyAgICAgICAgaGFuZGxlciA9
IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfdHJhbnNwb3J0KCkpCisg
ICAgICAgIGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgncHV0JywgKHUnXE57SU5URVJST0JBTkd9
JywgJycpKQorICAgICAgICBoYW5kbGVyLmFjY2VwdF9ib2R5KCdhYmNcbicpCisgICAgICAgIGhh
bmRsZXIuZW5kX29mX2JvZHkoKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCgnb2snLCksIGhh
bmRsZXIucmVzcG9uc2UuYXJncykKKyAgICAgICAgc2VsZi5jaGVja19maWxlX2NvbnRlbnRzKHUn
XE57SU5URVJST0JBTkd9Jy5lbmNvZGUoJ3V0Zi04JyksICdhYmNcbicpCisKKyAgICBkZWYgdGVz
dF9wdXRfbm9uX2F0b21pYyhzZWxmKToKKyAgICAgICAgaGFuZGxlciA9IHNtYXJ0LlNtYXJ0U2Vy
dmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfdHJhbnNwb3J0KCkpCisgICAgICAgIGhhbmRsZXIu
ZGlzcGF0Y2hfY29tbWFuZCgKKyAgICAgICAgICAgICdwdXRfbm9uX2F0b21pYycsICh1J1xOe0lO
VEVSUk9CQU5HfScsICcnLCAnRicsICcnKSkKKyAgICAgICAgaGFuZGxlci5hY2NlcHRfYm9keSgn
YWJjXG4nKQorICAgICAgICBoYW5kbGVyLmVuZF9vZl9ib2R5KCkKKyAgICAgICAgc2VsZi5hc3Nl
cnRFcXVhbCgoJ29rJywpLCBoYW5kbGVyLnJlc3BvbnNlLmFyZ3MpCisgICAgICAgIHNlbGYuY2hl
Y2tfZmlsZV9jb250ZW50cyh1J1xOe0lOVEVSUk9CQU5HfScuZW5jb2RlKCd1dGYtOCcpLCAnYWJj
XG4nKQorCisgICAgZGVmIHRlc3RfcmVhZHYoc2VsZik6CisgICAgICAgIHNlbGYuYnVpbGRfdHJl
ZShbdSdcTntJTlRFUlJPQkFOR30nXSkKKyAgICAgICAgaGFuZGxlciA9IHNtYXJ0LlNtYXJ0U2Vy
dmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfcmVhZG9ubHlfdHJhbnNwb3J0KCkpCisgICAgICAg
IGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgncmVhZHYnLCAodSdcTntJTlRFUlJPQkFOR30nLCkp
CisgICAgICAgIGhhbmRsZXIuYWNjZXB0X2JvZHkoJzIsMycpCisgICAgICAgIGhhbmRsZXIuZW5k
X29mX2JvZHkoKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCgncmVhZHYnLCApLCBoYW5kbGVy
LnJlc3BvbnNlLmFyZ3MpCisgICAgICAgICMgY28gLSBudGUgLSBudCBvZiBhLWZpbGUgaXMgdGhl
IGZpbGUgY29udGVudHMgd2UgYXJlIGV4dHJhY3RpbmcgZnJvbS4KKyAgICAgICAgc2VsZi5hc3Nl
cnRFcXVhbCgnbnRlJywgaGFuZGxlci5yZXNwb25zZS5ib2R5KQorCisgICAgZGVmIHRlc3RfcmVu
YW1lKHNlbGYpOgorICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoW3Unb25lXE57SU5URVJST0JBTkd9
J10pCisgICAgICAgIGhhbmRsZXIgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKHNl
bGYuZ2V0X3RyYW5zcG9ydCgpKQorICAgICAgICBoYW5kbGVyLmRpc3BhdGNoX2NvbW1hbmQoCisg
ICAgICAgICAgICAncmVuYW1lJywgKHUnb25lXE57SU5URVJST0JBTkd9JywgdSd0d29cTntJTlRF
UlJPQkFOR30nLCkpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoKCdvaycsKSwgaGFuZGxlci5y
ZXNwb25zZS5hcmdzKQorICAgICAgICBzZWxmLmZhaWxJZkV4aXN0cyh1J29uZVxOe0lOVEVSUk9C
QU5HfScuZW5jb2RlKCd1dGYtOCcpKQorICAgICAgICBzZWxmLmZhaWxVbmxlc3NFeGlzdHModSd0
d29cTntJTlRFUlJPQkFOR30nLmVuY29kZSgndXRmLTgnKSkKKworICAgIGRlZiB0ZXN0X3JtZGly
KHNlbGYpOgorICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoW3UnXE57SU5URVJST0JBTkd9LyddKQor
ICAgICAgICBoYW5kbGVyID0gc21hcnQuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihzZWxmLmdl
dF90cmFuc3BvcnQoKSkKKyAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdybWRpcics
ICh1J1xOe0lOVEVSUk9CQU5HfScsKSkKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgoJ29rJywp
LCBoYW5kbGVyLnJlc3BvbnNlLmFyZ3MpCisgICAgICAgIHNlbGYuZmFpbElmRXhpc3RzKHUnXE57
SU5URVJST0JBTkd9Jy5lbmNvZGUoJ3V0Zi04JykpCisKKyAgICBkZWYgdGVzdF9zdGF0KHNlbGYp
OgorICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoW3UnXE57SU5URVJST0JBTkd9J10pCisgICAgICAg
IGhhbmRsZXIgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3JlYWRv
bmx5X3RyYW5zcG9ydCgpKQorICAgICAgICBoYW5kbGVyLmRpc3BhdGNoX2NvbW1hbmQoJ3N0YXQn
LCAodSdcTntJTlRFUlJPQkFOR30nLCkpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJ3N0YXQn
LCBoYW5kbGVyLnJlc3BvbnNlLmFyZ3NbMF0pCisKKwogY2xhc3MgU21hcnRUcmFuc3BvcnRSZWdp
c3RyYXRpb24odGVzdHMuVGVzdENhc2UpOgogCiAgICAgZGVmIHRlc3RfcmVnaXN0cmF0aW9uKHNl
bGYpOgoK

=== modified file bzrlib/transport/smart.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvc21hcnQucHkKKysrIGJ6cmxpYi90cmFuc3BvcnQvc21hcnQu
cHkKQEAgLTU2MCw2ICs1NjAsNyBAQAogICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAg
ICAgYnl0ZXMgPSBzZWxmLl9pbi5yZWFkKGJ5dGVzX3RvX3JlYWQpCiAgICAgICAgICAgICBpZiBi
eXRlcyA9PSAnJzoKKwogICAgICAgICAgICAgICAgICMgQ29ubmVjdGlvbiBoYXMgYmVlbiBjbG9z
ZWQuCiAgICAgICAgICAgICAgICAgc2VsZi5maW5pc2hlZCA9IFRydWUKICAgICAgICAgICAgICAg
ICBzZWxmLl9vdXQuZmx1c2goKQpAQCAtNjM1LDEwICs2MzYsMTIgQEAKICAgICAgICAgcmV0dXJu
IFNtYXJ0U2VydmVyUmVzcG9uc2UoKCdvaycsICcxJykpCiAKICAgICBkZWYgZG9faGFzKHNlbGYs
IHJlbHBhdGgpOgorICAgICAgICByZWxwYXRoID0gcmVscGF0aC5lbmNvZGUoJ3V0Zi04JykKICAg
ICAgICAgciA9IHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LmhhcyhyZWxwYXRoKSBhbmQgJ3llcycg
b3IgJ25vJwogICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNwb25zZSgociwpKQogCiAgICAg
ZGVmIGRvX2dldChzZWxmLCByZWxwYXRoKToKKyAgICAgICAgcmVscGF0aCA9IHJlbHBhdGguZW5j
b2RlKCd1dGYtOCcpCiAgICAgICAgIGJhY2tpbmdfYnl0ZXMgPSBzZWxmLl9iYWNraW5nX3RyYW5z
cG9ydC5nZXRfYnl0ZXMocmVscGF0aCkKICAgICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVzcG9u
c2UoKCdvaycsKSwgYmFja2luZ19ieXRlcykKIApAQCAtNjUxLDcgKzY1NCw3IEBACiAKICAgICBk
ZWYgZG9fYXBwZW5kKHNlbGYsIHJlbHBhdGgsIG1vZGUpOgogICAgICAgICBzZWxmLl9jb252ZXJ0
ZWRfY29tbWFuZCA9IFRydWUKLSAgICAgICAgc2VsZi5fcmVscGF0aCA9IHJlbHBhdGgKKyAgICAg
ICAgc2VsZi5fcmVscGF0aCA9IHJlbHBhdGguZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgIHNlbGYu
X21vZGUgPSBzZWxmLl9kZXNlcmlhbGlzZV9vcHRpb25hbF9tb2RlKG1vZGUpCiAgICAgICAgIHNl
bGYuX2VuZF9vZl9ib2R5X2hhbmRsZXIgPSBzZWxmLl9oYW5kbGVfZG9fYXBwZW5kX2VuZAogICAg
IApAQCAtNjYxLDI5ICs2NjQsMzMgQEAKICAgICAgICAgc2VsZi5yZXNwb25zZSA9IFNtYXJ0U2Vy
dmVyUmVzcG9uc2UoKCdhcHBlbmRlZCcsICclZCcgJSBvbGRfbGVuZ3RoKSkKIAogICAgIGRlZiBk
b19kZWxldGUoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHJlbHBhdGggPSByZWxwYXRoLmVuY29k
ZSgndXRmLTgnKQogICAgICAgICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5kZWxldGUocmVscGF0
aCkKIAotICAgIGRlZiBkb19pdGVyX2ZpbGVzX3JlY3Vyc2l2ZShzZWxmLCBhYnNwYXRoKToKLSAg
ICAgICAgIyBYWFg6IHRoZSBwYXRoIGhhbmRsaW5nIG5lZWRzIHNvbWUgdGhvdWdodC4KLSAgICAg
ICAgI3JlbHBhdGggPSBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5yZWxwYXRoKGFic3BhdGgpCi0g
ICAgICAgIHRyYW5zcG9ydCA9IHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LmNsb25lKGFic3BhdGgp
CisgICAgZGVmIGRvX2l0ZXJfZmlsZXNfcmVjdXJzaXZlKHNlbGYsIHJlbHBhdGgpOgorICAgICAg
ICByZWxwYXRoID0gcmVscGF0aC5lbmNvZGUoJ3V0Zi04JykKKyAgICAgICAgdHJhbnNwb3J0ID0g
c2VsZi5fYmFja2luZ190cmFuc3BvcnQuY2xvbmUocmVscGF0aCkKICAgICAgICAgZmlsZW5hbWVz
ID0gdHJhbnNwb3J0Lml0ZXJfZmlsZXNfcmVjdXJzaXZlKCkKICAgICAgICAgcmV0dXJuIFNtYXJ0
U2VydmVyUmVzcG9uc2UoKCduYW1lcycsKSArIHR1cGxlKGZpbGVuYW1lcykpCiAKICAgICBkZWYg
ZG9fbGlzdF9kaXIoc2VsZiwgcmVscGF0aCk6CisgICAgICAgIHJlbHBhdGggPSByZWxwYXRoLmVu
Y29kZSgndXRmLTgnKQogICAgICAgICBmaWxlbmFtZXMgPSBzZWxmLl9iYWNraW5nX3RyYW5zcG9y
dC5saXN0X2RpcihyZWxwYXRoKQogICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNwb25zZSgo
J25hbWVzJywpICsgdHVwbGUoZmlsZW5hbWVzKSkKIAogICAgIGRlZiBkb19ta2RpcihzZWxmLCBy
ZWxwYXRoLCBtb2RlKToKKyAgICAgICAgcmVscGF0aCA9IHJlbHBhdGguZW5jb2RlKCd1dGYtOCcp
CiAgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0Lm1rZGlyKHJlbHBhdGgsCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2Rlc2VyaWFsaXNlX29wdGlvbmFs
X21vZGUobW9kZSkpCiAKICAgICBkZWYgZG9fbW92ZShzZWxmLCByZWxfZnJvbSwgcmVsX3RvKToK
KyAgICAgICAgcmVsX2Zyb20gPSByZWxfZnJvbS5lbmNvZGUoJ3V0Zi04JykKKyAgICAgICAgcmVs
X3RvID0gcmVsX3RvLmVuY29kZSgndXRmLTgnKQogICAgICAgICBzZWxmLl9iYWNraW5nX3RyYW5z
cG9ydC5tb3ZlKHJlbF9mcm9tLCByZWxfdG8pCiAKICAgICBkZWYgZG9fcHV0KHNlbGYsIHJlbHBh
dGgsIG1vZGUpOgogICAgICAgICBzZWxmLl9jb252ZXJ0ZWRfY29tbWFuZCA9IFRydWUKLSAgICAg
ICAgc2VsZi5fcmVscGF0aCA9IHJlbHBhdGgKKyAgICAgICAgc2VsZi5fcmVscGF0aCA9IHJlbHBh
dGguZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgIHNlbGYuX21vZGUgPSBzZWxmLl9kZXNlcmlhbGlz
ZV9vcHRpb25hbF9tb2RlKG1vZGUpCiAgICAgICAgIHNlbGYuX2VuZF9vZl9ib2R5X2hhbmRsZXIg
PSBzZWxmLl9oYW5kbGVfZG9fcHV0CiAKQEAgLTcwNSw3ICs3MTIsNyBAQAogICAgIGRlZiBkb19w
dXRfbm9uX2F0b21pYyhzZWxmLCByZWxwYXRoLCBtb2RlLCBjcmVhdGVfcGFyZW50LCBkaXJfbW9k
ZSk6CiAgICAgICAgIHNlbGYuX2NvbnZlcnRlZF9jb21tYW5kID0gVHJ1ZQogICAgICAgICBzZWxm
Ll9lbmRfb2ZfYm9keV9oYW5kbGVyID0gc2VsZi5faGFuZGxlX3B1dF9ub25fYXRvbWljCi0gICAg
ICAgIHNlbGYuX3JlbHBhdGggPSByZWxwYXRoCisgICAgICAgIHNlbGYuX3JlbHBhdGggPSByZWxw
YXRoLmVuY29kZSgndXRmLTgnKQogICAgICAgICBzZWxmLl9kaXJfbW9kZSA9IHNlbGYuX2Rlc2Vy
aWFsaXNlX29wdGlvbmFsX21vZGUoZGlyX21vZGUpCiAgICAgICAgIHNlbGYuX21vZGUgPSBzZWxm
Ll9kZXNlcmlhbGlzZV9vcHRpb25hbF9tb2RlKG1vZGUpCiAgICAgICAgICMgYSBib29sZWFuIHdv
dWxkIGJlIG5pY2VyIFhYWApAQCAtNzIyLDcgKzcyOSw3IEBACiAgICAgZGVmIGRvX3JlYWR2KHNl
bGYsIHJlbHBhdGgpOgogICAgICAgICBzZWxmLl9jb252ZXJ0ZWRfY29tbWFuZCA9IFRydWUKICAg
ICAgICAgc2VsZi5fZW5kX29mX2JvZHlfaGFuZGxlciA9IHNlbGYuX2hhbmRsZV9yZWFkdl9vZmZz
ZXRzCi0gICAgICAgIHNlbGYuX3JlbHBhdGggPSByZWxwYXRoCisgICAgICAgIHNlbGYuX3JlbHBh
dGggPSByZWxwYXRoLmVuY29kZSgndXRmLTgnKQogCiAgICAgZGVmIGVuZF9vZl9ib2R5KHNlbGYp
OgogICAgICAgICAiIiJObyBtb3JlIGJvZHkgZGF0YSB3aWxsIGJlIHJlY2VpdmVkLiIiIgpAQCAt
NzM4LDEyICs3NDUsMTYgQEAKICAgICAgICAgc2VsZi5yZXNwb25zZSA9IFNtYXJ0U2VydmVyUmVz
cG9uc2UoKCdyZWFkdicsKSwgYmFja2luZ19ieXRlcykKICAgICAgICAgCiAgICAgZGVmIGRvX3Jl
bmFtZShzZWxmLCByZWxfZnJvbSwgcmVsX3RvKToKKyAgICAgICAgcmVsX2Zyb20gPSByZWxfZnJv
bS5lbmNvZGUoJ3V0Zi04JykKKyAgICAgICAgcmVsX3RvID0gcmVsX3RvLmVuY29kZSgndXRmLTgn
KQogICAgICAgICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5yZW5hbWUocmVsX2Zyb20sIHJlbF90
bykKIAogICAgIGRlZiBkb19ybWRpcihzZWxmLCByZWxwYXRoKToKKyAgICAgICAgcmVscGF0aCA9
IHJlbHBhdGguZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0
LnJtZGlyKHJlbHBhdGgpCiAKICAgICBkZWYgZG9fc3RhdChzZWxmLCByZWxwYXRoKToKKyAgICAg
ICAgcmVscGF0aCA9IHJlbHBhdGguZW5jb2RlKCd1dGYtOCcpCiAgICAgICAgIHN0YXQgPSBzZWxm
Ll9iYWNraW5nX3RyYW5zcG9ydC5zdGF0KHJlbHBhdGgpCiAgICAgICAgIHJldHVybiBTbWFydFNl
cnZlclJlc3BvbnNlKCgnc3RhdCcsIHN0cihzdGF0LnN0X3NpemUpLCBvY3Qoc3RhdC5zdF9tb2Rl
KSkpCiAgICAgICAgIAoK

# revision id: andrew.bennetts at canonical.com-20061012085801-36b60463388ea0e7
# sha1: fe0d697cf51ffe0fd9e6a99b58a487493faa73d0
# inventory sha1: 07d54dc8c33516287becb6384608ec00531d8204
# parent ids:
#   andrew.bennetts at canonical.com-20061012063051-5efaeb5409f0dbad
# properties:
#   branch-nick: smart server unicode



More information about the bazaar mailing list