[MERGE] Split bzrlib/transport/smart.py into several smaller modules.

Andrew Bennetts andrew at canonical.com
Tue Apr 10 03:38:05 BST 2007


This patch looks large, but it's just moving code around (and adding a couple of
docstrings to the newly created modules).

This moves almost all the classes from bzrlib/transport/smart.py, and moves them
into modules inside a new bzrlib/smart package:

  * server.py: SmartTCPServer, and other related classes.
  * protocol.py: Wire-level encoding and decoding of requests and responses
    for the smart client and server.
  * medium.py: The "medium" layer (i.e. means of transmission) that carries
    the bytes of the smart protocol.
  * request.py: Basic server-side logic for dealing with requests.
  
The remaining transport-related classes are moved to bzrlib/transport/remote.py.

These abstractions already exist in the smart server code in bzr.dev, it's just
the code was in one huge file.  This seperation also helps detangle some
inter-dependencies which weren't clear before.  That is, it's easy to put the
classes in one big file, but it was hard to pull them apart without tripping
over circular imports and the like.  So the separation also makes the structure
of the code clearer, beyond just splitting the code into smaller (and thus more
readable) pieces.

This split is the first step to merging the hpss branch, which adds more modules
to the bzrlib/smart package, and builds on the code already there.

-Andrew.

-------------- next part --------------
# Bazaar revision bundle v0.9
#
# message:
#   Cosmetic changes to minimise the difference between this branch and the hpss branch.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Tue 2007-04-10 12:31:42.628000021 +1000

=== added directory bzrlib/smart // file-id:smart-20061101100241-u0wzhkl4sjwmuz
... hd-1 // last-changed:andrew.bennetts at canonical.com-20070406011930-wy4emdgu3
... yu527pm
=== added file bzrlib/smart/__init__.py // file-id:__init__.py-20061101100249-8
... jwwl0d3jr080zim-1
--- /dev/null
+++ bzrlib/smart/__init__.py
@@ -0,0 +1,201 @@
+# 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
+
+"""Smart-server protocol, client and server.
+
+This code is fairly complex, so it has been split up into a package of modules,
+rather than being a single large module.  Refer to the individual module
+docstrings for details.
+
+Overview
+========
+
+Requests are sent as a command and list of arguments, followed by optional
+bulk body data.  Responses are similarly a response and list of arguments,
+followed by bulk body data. ::
+
+  SEP := '\001'
+    Fields are separated by Ctrl-A.
+  BULK_DATA := CHUNK TRAILER
+    Chunks can be repeated as many times as necessary.
+  CHUNK := CHUNK_LEN CHUNK_BODY
+  CHUNK_LEN := DIGIT+ NEWLINE
+    Gives the number of bytes in the following chunk.
+  CHUNK_BODY := BYTE[chunk_len]
+  TRAILER := SUCCESS_TRAILER | ERROR_TRAILER
+  SUCCESS_TRAILER := 'done' NEWLINE
+  ERROR_TRAILER := 
+
+Paths are passed across the network.  The client needs to see a namespace that
+includes any repository that might need to be referenced, and the client needs
+to know about a root directory beyond which it cannot ascend.
+
+Servers run over ssh will typically want to be able to access any path the user 
+can access.  Public servers on the other hand (which might be over http, ssh
+or tcp) will typically want to restrict access to only a particular directory 
+and its children, so will want to do a software virtual root at that level.
+In other words they'll want to rewrite incoming paths to be under that level
+(and prevent escaping using ../ tricks.)
+
+URLs that include ~ should probably be passed across to the server verbatim
+and the server can expand them.  This will proably not be meaningful when 
+limited to a directory?
+
+At the bottom level socket, pipes, HTTP server.  For sockets, we have the idea
+that you have multiple requests and get a read error because the other side did
+shutdown.  For pipes we have read pipe which will have a zero read which marks
+end-of-file.  For HTTP server environment there is not end-of-stream because
+each request coming into the server is independent.
+
+So we need a wrapper around pipes and sockets to seperate out requests from
+substrate and this will give us a single model which is consist for HTTP,
+sockets and pipes.
+
+Server-side
+-----------
+
+ MEDIUM  (factory for protocol, reads bytes & pushes to protocol,
+          uses protocol to detect end-of-request, sends written
+          bytes to client) e.g. socket, pipe, HTTP request handler.
+  ^
+  | bytes.
+  v
+
+PROTOCOL  (serialization, deserialization)  accepts bytes for one
+          request, decodes according to internal state, pushes
+          structured data to handler.  accepts structured data from
+          handler and encodes and writes to the medium.  factory for
+          handler.
+  ^
+  | structured data
+  v
+
+HANDLER   (domain logic) accepts structured data, operates state
+          machine until the request can be satisfied,
+          sends structured data to the protocol.
+
+
+Client-side
+-----------
+
+ CLIENT             domain logic, accepts domain requests, generated structured
+                    data, reads structured data from responses and turns into
+                    domain data.  Sends structured data to the protocol.
+                    Operates state machines until the request can be delivered
+                    (e.g. reading from a bundle generated in bzrlib to deliver a
+                    complete request).
+
+                    Possibly this should just be RemoteBzrDir, RemoteTransport,
+                    ...
+  ^
+  | structured data
+  v
+
+PROTOCOL  (serialization, deserialization)  accepts structured data for one
+          request, encodes and writes to the medium.  Reads bytes from the
+          medium, decodes and allows the client to read structured data.
+  ^
+  | bytes.
+  v
+
+ MEDIUM  (accepts bytes from the protocol & delivers to the remote server.
+          Allows the potocol to read bytes e.g. socket, pipe, HTTP request.
+"""
+
+# TODO: _translate_error should be on the client, not the transport because
+#     error coding is wire protocol specific.
+
+# TODO: A plain integer from query_version is too simple; should give some
+# capabilities too?
+
+# TODO: Server should probably catch exceptions within itself and send them
+# back across the network.  (But shouldn't catch KeyboardInterrupt etc)
+# Also needs to somehow report protocol errors like bad requests.  Need to
+# consider how we'll handle error reporting, e.g. if we get halfway through a
+# bulk transfer and then something goes wrong.
+
+# TODO: Standard marker at start of request/response lines?
+
+# TODO: Make each request and response self-validatable, e.g. with checksums.
+#
+# TODO: get/put objects could be changed to gradually read back the data as it
+# comes across the network
+#
+# TODO: What should the server do if it hits an error and has to terminate?
+#
+# TODO: is it useful to allow multiple chunks in the bulk data?
+#
+# TODO: If we get an exception during transmission of bulk data we can't just
+# emit the exception because it won't be seen.
+#   John proposes:  I think it would be worthwhile to have a header on each
+#   chunk, that indicates it is another chunk. Then you can send an 'error'
+#   chunk as long as you finish the previous chunk.
+#
+# TODO: Clone method on Transport; should work up towards parent directory;
+# unclear how this should be stored or communicated to the server... maybe
+# just pass it on all relevant requests?
+#
+# TODO: Better name than clone() for changing between directories.  How about
+# open_dir or change_dir or chdir?
+#
+# TODO: Is it really good to have the notion of current directory within the
+# connection?  Perhaps all Transports should factor out a common connection
+# from the thing that has the directory context?
+#
+# TODO: Pull more things common to sftp and ssh to a higher level.
+#
+# TODO: The server that manages a connection should be quite small and retain
+# minimum state because each of the requests are supposed to be stateless.
+# Then we can write another implementation that maps to http.
+#
+# TODO: What to do when a client connection is garbage collected?  Maybe just
+# abruptly drop the connection?
+#
+# TODO: Server in some cases will need to restrict access to files outside of
+# a particular root directory.  LocalTransport doesn't do anything to stop you
+# ascending above the base directory, so we need to prevent paths
+# containing '..' in either the server or transport layers.  (Also need to
+# consider what happens if someone creates a symlink pointing outside the 
+# directory tree...)
+#
+# TODO: Server should rebase absolute paths coming across the network to put
+# them under the virtual root, if one is in use.  LocalTransport currently
+# doesn't do that; if you give it an absolute path it just uses it.
+# 
+# XXX: Arguments can't contain newlines or ascii; possibly we should e.g.
+# urlescape them instead.  Indeed possibly this should just literally be
+# http-over-ssh.
+#
+# FIXME: This transport, with several others, has imperfect handling of paths
+# within urls.  It'd probably be better for ".." from a root to raise an error
+# rather than return the same directory as we do at present.
+#
+# TODO: Rather than working at the Transport layer we want a Branch,
+# Repository or BzrDir objects that talk to a server.
+#
+# TODO: Probably want some way for server commands to gradually produce body
+# data rather than passing it as a string; they could perhaps pass an
+# iterator-like callback that will gradually yield data; it probably needs a
+# close() method that will always be closed to do any necessary cleanup.
+#
+# TODO: Split the actual smart server from the ssh encoding of it.
+#
+# TODO: Perhaps support file-level readwrite operations over the transport
+# too.
+#
+# TODO: SmartBzrDir class, proxying all Branch etc methods across to another
+# branch doing file-level operations.
+#

=== added file bzrlib/smart/medium.py // file-id:medium.py-20061103051856-rgu2h
... uy59fkz902q-1
--- /dev/null
+++ bzrlib/smart/medium.py
@@ -0,0 +1,526 @@
+# Copyright (C) 2006,2007 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
+
+"""The 'medium' layer for the smart servers and clients.
+
+"Medium" here is the noun meaning "a means of transmission", not the adjective
+for "the quality between big and small."
+
+Media carry the bytes of the requests somehow (e.g. via TCP, wrapped in HTTP, or
+over SSH), and pass them to and from the protocol logic.  See the overview in
+bzrlib/transport/smart/__init__.py.
+"""
+
+import os
+import socket
+import sys
+from bzrlib import errors
+from bzrlib.smart.protocol import SmartServerRequestProtocolOne
+
+try:
+    from bzrlib.transport import ssh
+except errors.ParamikoNotPresent:
+    # no paramiko.  SmartSSHClientMedium will break.
+    pass
+
+
+class SmartServerStreamMedium(object):
+    """Handles smart commands coming over a stream.
+
+    The stream may be a pipe connected to sshd, or a tcp socket, or an
+    in-process fifo for testing.
+
+    One instance is created for each connected client; it can serve multiple
+    requests in the lifetime of the connection.
+
+    The server passes requests through to an underlying backing transport, 
+    which will typically be a LocalTransport looking at the server's filesystem.
+    """
+
+    def __init__(self, backing_transport):
+        """Construct new server.
+
+        :param backing_transport: Transport for the directory served.
+        """
+        # backing_transport could be passed to serve instead of __init__
+        self.backing_transport = backing_transport
+        self.finished = False
+
+    def serve(self):
+        """Serve requests until the client disconnects."""
+        # Keep a reference to stderr because the sys module's globals get set to
+        # None during interpreter shutdown.
+        from sys import stderr
+        try:
+            while not self.finished:
+                protocol = SmartServerRequestProtocolOne(self.backing_transport,
+                                                         self._write_out)
+                self._serve_one_request(protocol)
+        except Exception, e:
+            stderr.write("%s terminating on exception %s\n" % (self, e))
+            raise
+
+    def _serve_one_request(self, protocol):
+        """Read one request from input, process, send back a response.
+        
+        :param protocol: a SmartServerRequestProtocol.
+        """
+        try:
+            self._serve_one_request_unguarded(protocol)
+        except KeyboardInterrupt:
+            raise
+        except Exception, e:
+            self.terminate_due_to_error()
+
+    def terminate_due_to_error(self):
+        """Called when an unhandled exception from the protocol occurs."""
+        raise NotImplementedError(self.terminate_due_to_error)
+
+
+class SmartServerSocketStreamMedium(SmartServerStreamMedium):
+
+    def __init__(self, sock, backing_transport):
+        """Constructor.
+
+        :param sock: the socket the server will read from.  It will be put
+            into blocking mode.
+        """
+        SmartServerStreamMedium.__init__(self, backing_transport)
+        self.push_back = ''
+        sock.setblocking(True)
+        self.socket = sock
+
+    def _serve_one_request_unguarded(self, protocol):
+        while protocol.next_read_size():
+            if self.push_back:
+                protocol.accept_bytes(self.push_back)
+                self.push_back = ''
+            else:
+                bytes = self.socket.recv(4096)
+                if bytes == '':
+                    self.finished = True
+                    return
+                protocol.accept_bytes(bytes)
+        
+        self.push_back = protocol.excess_buffer
+    
+    def terminate_due_to_error(self):
+        """Called when an unhandled exception from the protocol occurs."""
+        # TODO: This should log to a server log file, but no such thing
+        # exists yet.  Andrew Bennetts 2006-09-29.
+        self.socket.close()
+        self.finished = True
+
+    def _write_out(self, bytes):
+        self.socket.sendall(bytes)
+
+
+class SmartServerPipeStreamMedium(SmartServerStreamMedium):
+
+    def __init__(self, in_file, out_file, backing_transport):
+        """Construct new server.
+
+        :param in_file: Python file from which requests can be read.
+        :param out_file: Python file to write responses.
+        :param backing_transport: Transport for the directory served.
+        """
+        SmartServerStreamMedium.__init__(self, backing_transport)
+        if sys.platform == 'win32':
+            # force binary mode for files
+            import msvcrt
+            for f in (in_file, out_file):
+                fileno = getattr(f, 'fileno', None)
+                if fileno:
+                    msvcrt.setmode(fileno(), os.O_BINARY)
+        self._in = in_file
+        self._out = out_file
+
+    def _serve_one_request_unguarded(self, protocol):
+        while True:
+            bytes_to_read = protocol.next_read_size()
+            if bytes_to_read == 0:
+                # Finished serving this request.
+                self._out.flush()
+                return
+            bytes = self._in.read(bytes_to_read)
+            if bytes == '':
+                # Connection has been closed.
+                self.finished = True
+                self._out.flush()
+                return
+            protocol.accept_bytes(bytes)
+
+    def terminate_due_to_error(self):
+        # TODO: This should log to a server log file, but no such thing
+        # exists yet.  Andrew Bennetts 2006-09-29.
+        self._out.close()
+        self.finished = True
+
+    def _write_out(self, bytes):
+        self._out.write(bytes)
+
+
+class SmartClientMediumRequest(object):
+    """A request on a SmartClientMedium.
+
+    Each request allows bytes to be provided to it via accept_bytes, and then
+    the response bytes to be read via read_bytes.
+
+    For instance:
+    request.accept_bytes('123')
+    request.finished_writing()
+    result = request.read_bytes(3)
+    request.finished_reading()
+
+    It is up to the individual SmartClientMedium whether multiple concurrent
+    requests can exist. See SmartClientMedium.get_request to obtain instances 
+    of SmartClientMediumRequest, and the concrete Medium you are using for 
+    details on concurrency and pipelining.
+    """
+
+    def __init__(self, medium):
+        """Construct a SmartClientMediumRequest for the medium medium."""
+        self._medium = medium
+        # we track state by constants - we may want to use the same
+        # pattern as BodyReader if it gets more complex.
+        # valid states are: "writing", "reading", "done"
+        self._state = "writing"
+
+    def accept_bytes(self, bytes):
+        """Accept bytes for inclusion in this request.
+
+        This method may not be be called after finished_writing() has been
+        called.  It depends upon the Medium whether or not the bytes will be
+        immediately transmitted. Message based Mediums will tend to buffer the
+        bytes until finished_writing() is called.
+
+        :param bytes: A bytestring.
+        """
+        if self._state != "writing":
+            raise errors.WritingCompleted(self)
+        self._accept_bytes(bytes)
+
+    def _accept_bytes(self, bytes):
+        """Helper for accept_bytes.
+
+        Accept_bytes checks the state of the request to determing if bytes
+        should be accepted. After that it hands off to _accept_bytes to do the
+        actual acceptance.
+        """
+        raise NotImplementedError(self._accept_bytes)
+
+    def finished_reading(self):
+        """Inform the request that all desired data has been read.
+
+        This will remove the request from the pipeline for its medium (if the
+        medium supports pipelining) and any further calls to methods on the
+        request will raise ReadingCompleted.
+        """
+        if self._state == "writing":
+            raise errors.WritingNotComplete(self)
+        if self._state != "reading":
+            raise errors.ReadingCompleted(self)
+        self._state = "done"
+        self._finished_reading()
+
+    def _finished_reading(self):
+        """Helper for finished_reading.
+
+        finished_reading checks the state of the request to determine if 
+        finished_reading is allowed, and if it is hands off to _finished_reading
+        to perform the action.
+        """
+        raise NotImplementedError(self._finished_reading)
+
+    def finished_writing(self):
+        """Finish the writing phase of this request.
+
+        This will flush all pending data for this request along the medium.
+        After calling finished_writing, you may not call accept_bytes anymore.
+        """
+        if self._state != "writing":
+            raise errors.WritingCompleted(self)
+        self._state = "reading"
+        self._finished_writing()
+
+    def _finished_writing(self):
+        """Helper for finished_writing.
+
+        finished_writing checks the state of the request to determine if 
+        finished_writing is allowed, and if it is hands off to _finished_writing
+        to perform the action.
+        """
+        raise NotImplementedError(self._finished_writing)
+
+    def read_bytes(self, count):
+        """Read bytes from this requests response.
+
+        This method will block and wait for count bytes to be read. It may not
+        be invoked until finished_writing() has been called - this is to ensure
+        a message-based approach to requests, for compatability with message
+        based mediums like HTTP.
+        """
+        if self._state == "writing":
+            raise errors.WritingNotComplete(self)
+        if self._state != "reading":
+            raise errors.ReadingCompleted(self)
+        return self._read_bytes(count)
+
+    def _read_bytes(self, count):
+        """Helper for read_bytes.
+
+        read_bytes checks the state of the request to determing if bytes
+        should be read. After that it hands off to _read_bytes to do the
+        actual read.
+        """
+        raise NotImplementedError(self._read_bytes)
+
+
+class SmartClientMedium(object):
+    """Smart client is a medium for sending smart protocol requests over."""
+
+    def disconnect(self):
+        """If this medium maintains a persistent connection, close it.
+        
+        The default implementation does nothing.
+        """
+        
+
+class SmartClientStreamMedium(SmartClientMedium):
+    """Stream based medium common class.
+
+    SmartClientStreamMediums operate on a stream. All subclasses use a common
+    SmartClientStreamMediumRequest for their requests, and should implement
+    _accept_bytes and _read_bytes to allow the request objects to send and
+    receive bytes.
+    """
+
+    def __init__(self):
+        self._current_request = None
+
+    def accept_bytes(self, bytes):
+        self._accept_bytes(bytes)
+
+    def __del__(self):
+        """The SmartClientStreamMedium knows how to close the stream when it is
+        finished with it.
+        """
+        self.disconnect()
+
+    def _flush(self):
+        """Flush the output stream.
+        
+        This method is used by the SmartClientStreamMediumRequest to ensure that
+        all data for a request is sent, to avoid long timeouts or deadlocks.
+        """
+        raise NotImplementedError(self._flush)
+
+    def get_request(self):
+        """See SmartClientMedium.get_request().
+
+        SmartClientStreamMedium always returns a SmartClientStreamMediumRequest
+        for get_request.
+        """
+        return SmartClientStreamMediumRequest(self)
+
+    def read_bytes(self, count):
+        return self._read_bytes(count)
+
+
+class SmartSimplePipesClientMedium(SmartClientStreamMedium):
+    """A client medium using simple pipes.
+    
+    This client does not manage the pipes: it assumes they will always be open.
+    """
+
+    def __init__(self, readable_pipe, writeable_pipe):
+        SmartClientStreamMedium.__init__(self)
+        self._readable_pipe = readable_pipe
+        self._writeable_pipe = writeable_pipe
+
+    def _accept_bytes(self, bytes):
+        """See SmartClientStreamMedium.accept_bytes."""
+        self._writeable_pipe.write(bytes)
+
+    def _flush(self):
+        """See SmartClientStreamMedium._flush()."""
+        self._writeable_pipe.flush()
+
+    def _read_bytes(self, count):
+        """See SmartClientStreamMedium._read_bytes."""
+        return self._readable_pipe.read(count)
+
+
+class SmartSSHClientMedium(SmartClientStreamMedium):
+    """A client medium using SSH."""
+    
+    def __init__(self, host, port=None, username=None, password=None,
+            vendor=None):
+        """Creates a client that will connect on the first use.
+        
+        :param vendor: An optional override for the ssh vendor to use. See
+            bzrlib.transport.ssh for details on ssh vendors.
+        """
+        SmartClientStreamMedium.__init__(self)
+        self._connected = False
+        self._host = host
+        self._password = password
+        self._port = port
+        self._username = username
+        self._read_from = None
+        self._ssh_connection = None
+        self._vendor = vendor
+        self._write_to = None
+
+    def _accept_bytes(self, bytes):
+        """See SmartClientStreamMedium.accept_bytes."""
+        self._ensure_connection()
+        self._write_to.write(bytes)
+
+    def disconnect(self):
+        """See SmartClientMedium.disconnect()."""
+        if not self._connected:
+            return
+        self._read_from.close()
+        self._write_to.close()
+        self._ssh_connection.close()
+        self._connected = False
+
+    def _ensure_connection(self):
+        """Connect this medium if not already connected."""
+        if self._connected:
+            return
+        executable = os.environ.get('BZR_REMOTE_PATH', 'bzr')
+        if self._vendor is None:
+            vendor = ssh._get_ssh_vendor()
+        else:
+            vendor = self._vendor
+        self._ssh_connection = vendor.connect_ssh(self._username,
+                self._password, self._host, self._port,
+                command=[executable, 'serve', '--inet', '--directory=/',
+                         '--allow-writes'])
+        self._read_from, self._write_to = \
+            self._ssh_connection.get_filelike_channels()
+        self._connected = True
+
+    def _flush(self):
+        """See SmartClientStreamMedium._flush()."""
+        self._write_to.flush()
+
+    def _read_bytes(self, count):
+        """See SmartClientStreamMedium.read_bytes."""
+        if not self._connected:
+            raise errors.MediumNotConnected(self)
+        return self._read_from.read(count)
+
+
+class SmartTCPClientMedium(SmartClientStreamMedium):
+    """A client medium using TCP."""
+    
+    def __init__(self, host, port):
+        """Creates a client that will connect on the first use."""
+        SmartClientStreamMedium.__init__(self)
+        self._connected = False
+        self._host = host
+        self._port = port
+        self._socket = None
+
+    def _accept_bytes(self, bytes):
+        """See SmartClientMedium.accept_bytes."""
+        self._ensure_connection()
+        self._socket.sendall(bytes)
+
+    def disconnect(self):
+        """See SmartClientMedium.disconnect()."""
+        if not self._connected:
+            return
+        self._socket.close()
+        self._socket = None
+        self._connected = False
+
+    def _ensure_connection(self):
+        """Connect this medium if not already connected."""
+        if self._connected:
+            return
+        self._socket = socket.socket()
+        self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+        result = self._socket.connect_ex((self._host, int(self._port)))
+        if result:
+            raise errors.ConnectionError("failed to connect to %s:%d: %s" %
+                    (self._host, self._port, os.strerror(result)))
+        self._connected = True
+
+    def _flush(self):
+        """See SmartClientStreamMedium._flush().
+        
+        For TCP we do no flushing. We may want to turn off TCP_NODELAY and 
+        add a means to do a flush, but that can be done in the future.
+        """
+
+    def _read_bytes(self, count):
+        """See SmartClientMedium.read_bytes."""
+        if not self._connected:
+            raise errors.MediumNotConnected(self)
+        return self._socket.recv(count)
+
+
+class SmartClientStreamMediumRequest(SmartClientMediumRequest):
+    """A SmartClientMediumRequest that works with an SmartClientStreamMedium."""
+
+    def __init__(self, medium):
+        SmartClientMediumRequest.__init__(self, medium)
+        # check that we are safe concurrency wise. If some streams start
+        # allowing concurrent requests - i.e. via multiplexing - then this
+        # assert should be moved to SmartClientStreamMedium.get_request,
+        # and the setting/unsetting of _current_request likewise moved into
+        # that class : but its unneeded overhead for now. RBC 20060922
+        if self._medium._current_request is not None:
+            raise errors.TooManyConcurrentRequests(self._medium)
+        self._medium._current_request = self
+
+    def _accept_bytes(self, bytes):
+        """See SmartClientMediumRequest._accept_bytes.
+        
+        This forwards to self._medium._accept_bytes because we are operating
+        on the mediums stream.
+        """
+        self._medium._accept_bytes(bytes)
+
+    def _finished_reading(self):
+        """See SmartClientMediumRequest._finished_reading.
+
+        This clears the _current_request on self._medium to allow a new 
+        request to be created.
+        """
+        assert self._medium._current_request is self
+        self._medium._current_request = None
+        
+    def _finished_writing(self):
+        """See SmartClientMediumRequest._finished_writing.
+
+        This invokes self._medium._flush to ensure all bytes are transmitted.
+        """
+        self._medium._flush()
+
+    def _read_bytes(self, count):
+        """See SmartClientMediumRequest._read_bytes.
+        
+        This forwards to self._medium._read_bytes because we are operating
+        on the mediums stream.
+        """
+        return self._medium._read_bytes(count)
+
+

=== added file bzrlib/smart/protocol.py // file-id:protocol.py-20061108035435-o
... t0lstk2590yqhzr-1 // last-changed:andrew.bennetts at canonical.com-20070410022
... 255-e1dhysj2zhukca5c
--- /dev/null
+++ bzrlib/smart/protocol.py
@@ -0,0 +1,343 @@
+# Copyright (C) 2006, 2007 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
+
+"""Wire-level encoding and decoding of requests and responses for the smart
+client and server.
+"""
+
+
+from cStringIO import StringIO
+
+from bzrlib import errors
+from bzrlib.smart import request
+
+
+def _recv_tuple(from_file):
+    req_line = from_file.readline()
+    return _decode_tuple(req_line)
+
+
+def _decode_tuple(req_line):
+    if req_line == None or req_line == '':
+        return None
+    if req_line[-1] != '\n':
+        raise errors.SmartProtocolError("request %r not terminated" % req_line)
+    return tuple(req_line[:-1].split('\x01'))
+
+
+def _encode_tuple(args):
+    """Encode the tuple args to a bytestream."""
+    return '\x01'.join(args) + '\n'
+
+
+class SmartProtocolBase(object):
+    """Methods common to client and server"""
+
+    # TODO: this only actually accomodates a single block; possibly should
+    # support multiple chunks?
+    def _encode_bulk_data(self, body):
+        """Encode body as a bulk data chunk."""
+        return ''.join(('%d\n' % len(body), body, 'done\n'))
+
+    def _serialise_offsets(self, offsets):
+        """Serialise a readv offset list."""
+        txt = []
+        for start, length in offsets:
+            txt.append('%d,%d' % (start, length))
+        return '\n'.join(txt)
+        
+
+class SmartServerRequestProtocolOne(SmartProtocolBase):
+    """Server-side encoding and decoding logic for smart version 1."""
+    
+    def __init__(self, backing_transport, write_func):
+        self._backing_transport = backing_transport
+        self.excess_buffer = ''
+        self._finished = False
+        self.in_buffer = ''
+        self.has_dispatched = False
+        self.request = None
+        self._body_decoder = None
+        self._write_func = write_func
+
+    def accept_bytes(self, bytes):
+        """Take bytes, and advance the internal state machine appropriately.
+        
+        :param bytes: must be a byte string
+        """
+        assert isinstance(bytes, str)
+        self.in_buffer += bytes
+        if not self.has_dispatched:
+            if '\n' not in self.in_buffer:
+                # no command line yet
+                return
+            self.has_dispatched = True
+            try:
+                first_line, self.in_buffer = self.in_buffer.split('\n', 1)
+                first_line += '\n'
+                req_args = _decode_tuple(first_line)
+                self.request = request.SmartServerRequestHandler(
+                    self._backing_transport)
+                self.request.dispatch_command(req_args[0], req_args[1:])
+                if self.request.finished_reading:
+                    # trivial request
+                    self.excess_buffer = self.in_buffer
+                    self.in_buffer = ''
+                    self._send_response(self.request.response.args,
+                        self.request.response.body)
+            except KeyboardInterrupt:
+                raise
+            except Exception, exception:
+                # everything else: pass to client, flush, and quit
+                self._send_response(('error', str(exception)))
+                return
+
+        if self.has_dispatched:
+            if self._finished:
+                # nothing to do.XXX: this routine should be a single state 
+                # machine too.
+                self.excess_buffer += self.in_buffer
+                self.in_buffer = ''
+                return
+            if self._body_decoder is None:
+                self._body_decoder = LengthPrefixedBodyDecoder()
+            self._body_decoder.accept_bytes(self.in_buffer)
+            self.in_buffer = self._body_decoder.unused_data
+            body_data = self._body_decoder.read_pending_data()
+            self.request.accept_body(body_data)
+            if self._body_decoder.finished_reading:
+                self.request.end_of_body()
+                assert self.request.finished_reading, \
+                    "no more body, request not finished"
+            if self.request.response is not None:
+                self._send_response(self.request.response.args,
+                    self.request.response.body)
+                self.excess_buffer = self.in_buffer
+                self.in_buffer = ''
+            else:
+                assert not self.request.finished_reading, \
+                    "no response and we have finished reading."
+
+    def _send_response(self, args, body=None):
+        """Send a smart server response down the output stream."""
+        assert not self._finished, 'response already sent'
+        self._finished = True
+        self._write_func(_encode_tuple(args))
+        if body is not None:
+            assert isinstance(body, str), 'body must be a str'
+            bytes = self._encode_bulk_data(body)
+            self._write_func(bytes)
+
+    def next_read_size(self):
+        if self._finished:
+            return 0
+        if self._body_decoder is None:
+            return 1
+        else:
+            return self._body_decoder.next_read_size()
+
+
+class LengthPrefixedBodyDecoder(object):
+    """Decodes the length-prefixed bulk data."""
+    
+    def __init__(self):
+        self.bytes_left = None
+        self.finished_reading = False
+        self.unused_data = ''
+        self.state_accept = self._state_accept_expecting_length
+        self.state_read = self._state_read_no_data
+        self._in_buffer = ''
+        self._trailer_buffer = ''
+    
+    def accept_bytes(self, bytes):
+        """Decode as much of bytes as possible.
+
+        If 'bytes' contains too much data it will be appended to
+        self.unused_data.
+
+        finished_reading will be set when no more data is required.  Further
+        data will be appended to self.unused_data.
+        """
+        # accept_bytes is allowed to change the state
+        current_state = self.state_accept
+        self.state_accept(bytes)
+        while current_state != self.state_accept:
+            current_state = self.state_accept
+            self.state_accept('')
+
+    def next_read_size(self):
+        if self.bytes_left is not None:
+            # Ideally we want to read all the remainder of the body and the
+            # trailer in one go.
+            return self.bytes_left + 5
+        elif self.state_accept == self._state_accept_reading_trailer:
+            # Just the trailer left
+            return 5 - len(self._trailer_buffer)
+        elif self.state_accept == self._state_accept_expecting_length:
+            # There's still at least 6 bytes left ('\n' to end the length, plus
+            # 'done\n').
+            return 6
+        else:
+            # Reading excess data.  Either way, 1 byte at a time is fine.
+            return 1
+        
+    def read_pending_data(self):
+        """Return any pending data that has been decoded."""
+        return self.state_read()
+
+    def _state_accept_expecting_length(self, bytes):
+        self._in_buffer += bytes
+        pos = self._in_buffer.find('\n')
+        if pos == -1:
+            return
+        self.bytes_left = int(self._in_buffer[:pos])
+        self._in_buffer = self._in_buffer[pos+1:]
+        self.bytes_left -= len(self._in_buffer)
+        self.state_accept = self._state_accept_reading_body
+        self.state_read = self._state_read_in_buffer
+
+    def _state_accept_reading_body(self, bytes):
+        self._in_buffer += bytes
+        self.bytes_left -= len(bytes)
+        if self.bytes_left <= 0:
+            # Finished with body
+            if self.bytes_left != 0:
+                self._trailer_buffer = self._in_buffer[self.bytes_left:]
+                self._in_buffer = self._in_buffer[:self.bytes_left]
+            self.bytes_left = None
+            self.state_accept = self._state_accept_reading_trailer
+        
+    def _state_accept_reading_trailer(self, bytes):
+        self._trailer_buffer += bytes
+        # TODO: what if the trailer does not match "done\n"?  Should this raise
+        # a ProtocolViolation exception?
+        if self._trailer_buffer.startswith('done\n'):
+            self.unused_data = self._trailer_buffer[len('done\n'):]
+            self.state_accept = self._state_accept_reading_unused
+            self.finished_reading = True
+    
+    def _state_accept_reading_unused(self, bytes):
+        self.unused_data += bytes
+
+    def _state_read_no_data(self):
+        return ''
+
+    def _state_read_in_buffer(self):
+        result = self._in_buffer
+        self._in_buffer = ''
+        return result
+
+
+class SmartClientRequestProtocolOne(SmartProtocolBase):
+    """The client-side protocol for smart version 1."""
+
+    def __init__(self, request):
+        """Construct a SmartClientRequestProtocolOne.
+
+        :param request: A SmartClientMediumRequest to serialise onto and
+            deserialise from.
+        """
+        self._request = request
+        self._body_buffer = None
+
+    def call(self, *args):
+        bytes = _encode_tuple(args)
+        self._request.accept_bytes(bytes)
+        self._request.finished_writing()
+
+    def call_with_body_bytes(self, args, body):
+        """Make a remote call of args with body bytes 'body'.
+
+        After calling this, call read_response_tuple to find the result out.
+        """
+        bytes = _encode_tuple(args)
+        self._request.accept_bytes(bytes)
+        bytes = self._encode_bulk_data(body)
+        self._request.accept_bytes(bytes)
+        self._request.finished_writing()
+
+    def call_with_body_readv_array(self, args, body):
+        """Make a remote call with a readv array.
+
+        The body is encoded with one line per readv offset pair. The numbers in
+        each pair are separated by a comma, and no trailing \n is emitted.
+        """
+        bytes = _encode_tuple(args)
+        self._request.accept_bytes(bytes)
+        readv_bytes = self._serialise_offsets(body)
+        bytes = self._encode_bulk_data(readv_bytes)
+        self._request.accept_bytes(bytes)
+        self._request.finished_writing()
+
+    def cancel_read_body(self):
+        """After expecting a body, a response code may indicate one otherwise.
+
+        This method lets the domain client inform the protocol that no body
+        will be transmitted. This is a terminal method: after calling it the
+        protocol is not able to be used further.
+        """
+        self._request.finished_reading()
+
+    def read_response_tuple(self, expect_body=False):
+        """Read a response tuple from the wire.
+
+        This should only be called once.
+        """
+        result = self._recv_tuple()
+        if not expect_body:
+            self._request.finished_reading()
+        return result
+
+    def read_body_bytes(self, count=-1):
+        """Read bytes from the body, decoding into a byte stream.
+        
+        We read all bytes at once to ensure we've checked the trailer for 
+        errors, and then feed the buffer back as read_body_bytes is called.
+        """
+        if self._body_buffer is not None:
+            return self._body_buffer.read(count)
+        _body_decoder = LengthPrefixedBodyDecoder()
+
+        while not _body_decoder.finished_reading:
+            bytes_wanted = _body_decoder.next_read_size()
+            bytes = self._request.read_bytes(bytes_wanted)
+            _body_decoder.accept_bytes(bytes)
+        self._request.finished_reading()
+        self._body_buffer = StringIO(_body_decoder.read_pending_data())
+        # XXX: TODO check the trailer result.
+        return self._body_buffer.read(count)
+
+    def _recv_tuple(self):
+        """Receive a tuple from the medium request."""
+        line = ''
+        while not line or line[-1] != '\n':
+            # TODO: this is inefficient - but tuples are short.
+            new_char = self._request.read_bytes(1)
+            line += new_char
+            assert new_char != '', "end of file reading from server."
+        return _decode_tuple(line)
+
+    def query_version(self):
+        """Return protocol version number of the server."""
+        self.call('hello')
+        resp = self.read_response_tuple()
+        if resp == ('ok', '1'):
+            return 1
+        else:
+            raise errors.SmartProtocolError("bad response %r" % (resp,))
+
+
+

=== added file bzrlib/smart/request.py // file-id:request.py-20061108095550-gun
... adhxmzkdjfeek-1 // last-changed:andrew.bennetts at canonical.com-2007041002225
... 5-e1dhysj2zhukca5c
--- /dev/null
+++ bzrlib/smart/request.py
@@ -0,0 +1,267 @@
+# Copyright (C) 2006, 2007 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
+
+"""Basic server-side logic for dealing with requests."""
+
+
+import tempfile
+
+from bzrlib import (
+    bzrdir,
+    errors,
+    revision
+    )
+from bzrlib.bundle.serializer import write_bundle
+
+
+class SmartServerResponse(object):
+    """Response generated by SmartServerRequestHandler."""
+
+    def __init__(self, args, body=None):
+        self.args = args
+        self.body = body
+
+# XXX: TODO: Create a SmartServerRequestHandler which will take the responsibility
+# for delivering the data for a request. This could be done with as the
+# StreamServer, though that would create conflation between request and response
+# which may be undesirable.
+
+class SmartServerRequestHandler(object):
+    """Protocol logic for smart server.
+    
+    This doesn't handle serialization at all, it just processes requests and
+    creates responses.
+    """
+
+    # IMPORTANT FOR IMPLEMENTORS: It is important that SmartServerRequestHandler
+    # not contain encoding or decoding logic to allow the wire protocol to vary
+    # from the object protocol: we will want to tweak the wire protocol separate
+    # from the object model, and ideally we will be able to do that without
+    # having a SmartServerRequestHandler subclass for each wire protocol, rather
+    # just a Protocol subclass.
+
+    # TODO: Better way of representing the body for commands that take it,
+    # and allow it to be streamed into the server.
+    
+    def __init__(self, backing_transport):
+        self._backing_transport = backing_transport
+        self._converted_command = False
+        self.finished_reading = False
+        self._body_bytes = ''
+        self.response = None
+
+    def accept_body(self, bytes):
+        """Accept body data.
+
+        This should be overriden for each command that desired body data to
+        handle the right format of that data. I.e. plain bytes, a bundle etc.
+
+        The deserialisation into that format should be done in the Protocol
+        object. Set self.desired_body_format to the format your method will
+        handle.
+        """
+        # default fallback is to accumulate bytes.
+        self._body_bytes += bytes
+        
+    def _end_of_body_handler(self):
+        """An unimplemented end of body handler."""
+        raise NotImplementedError(self._end_of_body_handler)
+        
+    def do_hello(self):
+        """Answer a version request with my version."""
+        return SmartServerResponse(('ok', '1'))
+
+    def do_has(self, relpath):
+        r = self._backing_transport.has(relpath) and 'yes' or 'no'
+        return SmartServerResponse((r,))
+
+    def do_get(self, relpath):
+        backing_bytes = self._backing_transport.get_bytes(relpath)
+        return SmartServerResponse(('ok',), backing_bytes)
+
+    def _deserialise_optional_mode(self, mode):
+        # XXX: FIXME this should be on the protocol object.
+        if mode == '':
+            return None
+        else:
+            return int(mode)
+
+    def do_append(self, relpath, mode):
+        self._converted_command = True
+        self._relpath = relpath
+        self._mode = self._deserialise_optional_mode(mode)
+        self._end_of_body_handler = self._handle_do_append_end
+    
+    def _handle_do_append_end(self):
+        old_length = self._backing_transport.append_bytes(
+            self._relpath, self._body_bytes, self._mode)
+        self.response = SmartServerResponse(('appended', '%d' % old_length))
+
+    def do_delete(self, relpath):
+        self._backing_transport.delete(relpath)
+
+    def do_iter_files_recursive(self, relpath):
+        transport = self._backing_transport.clone(relpath)
+        filenames = transport.iter_files_recursive()
+        return SmartServerResponse(('names',) + tuple(filenames))
+
+    def do_list_dir(self, relpath):
+        filenames = self._backing_transport.list_dir(relpath)
+        return SmartServerResponse(('names',) + tuple(filenames))
+
+    def do_mkdir(self, relpath, mode):
+        self._backing_transport.mkdir(relpath,
+                                      self._deserialise_optional_mode(mode))
+
+    def do_move(self, rel_from, rel_to):
+        self._backing_transport.move(rel_from, rel_to)
+
+    def do_put(self, relpath, mode):
+        self._converted_command = True
+        self._relpath = relpath
+        self._mode = self._deserialise_optional_mode(mode)
+        self._end_of_body_handler = self._handle_do_put
+
+    def _handle_do_put(self):
+        self._backing_transport.put_bytes(self._relpath,
+                self._body_bytes, self._mode)
+        self.response = SmartServerResponse(('ok',))
+
+    def _deserialise_offsets(self, text):
+        # XXX: FIXME this should be on the protocol object.
+        offsets = []
+        for line in text.split('\n'):
+            if not line:
+                continue
+            start, length = line.split(',')
+            offsets.append((int(start), int(length)))
+        return offsets
+
+    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._dir_mode = self._deserialise_optional_mode(dir_mode)
+        self._mode = self._deserialise_optional_mode(mode)
+        # a boolean would be nicer XXX
+        self._create_parent = (create_parent == 'T')
+
+    def _handle_put_non_atomic(self):
+        self._backing_transport.put_bytes_non_atomic(self._relpath,
+                self._body_bytes,
+                mode=self._mode,
+                create_parent_dir=self._create_parent,
+                dir_mode=self._dir_mode)
+        self.response = SmartServerResponse(('ok',))
+
+    def do_readv(self, relpath):
+        self._converted_command = True
+        self._end_of_body_handler = self._handle_readv_offsets
+        self._relpath = relpath
+
+    def end_of_body(self):
+        """No more body data will be received."""
+        self._run_handler_code(self._end_of_body_handler, (), {})
+        # cannot read after this.
+        self.finished_reading = True
+
+    def _handle_readv_offsets(self):
+        """accept offsets for a readv request."""
+        offsets = self._deserialise_offsets(self._body_bytes)
+        backing_bytes = ''.join(bytes for offset, bytes in
+            self._backing_transport.readv(self._relpath, offsets))
+        self.response = SmartServerResponse(('readv',), backing_bytes)
+        
+    def do_rename(self, rel_from, rel_to):
+        self._backing_transport.rename(rel_from, rel_to)
+
+    def do_rmdir(self, relpath):
+        self._backing_transport.rmdir(relpath)
+
+    def do_stat(self, relpath):
+        stat = self._backing_transport.stat(relpath)
+        return SmartServerResponse(('stat', str(stat.st_size), oct(stat.st_mode)))
+        
+    def do_get_bundle(self, path, revision_id):
+        # open transport relative to our base
+        t = self._backing_transport.clone(path)
+        control, extra_path = bzrdir.BzrDir.open_containing_from_transport(t)
+        repo = control.open_repository()
+        tmpf = tempfile.TemporaryFile()
+        base_revision = revision.NULL_REVISION
+        write_bundle(repo, revision_id, base_revision, tmpf)
+        tmpf.seek(0)
+        return SmartServerResponse((), tmpf.read())
+
+    def dispatch_command(self, cmd, args):
+        """Deprecated compatibility method.""" # XXX XXX
+        func = getattr(self, 'do_' + cmd, None)
+        if func is None:
+            raise errors.SmartProtocolError("bad request %r" % (cmd,))
+        self._run_handler_code(func, args, {})
+
+    def _run_handler_code(self, callable, args, kwargs):
+        """Run some handler specific code 'callable'.
+
+        If a result is returned, it is considered to be the commands response,
+        and finished_reading is set true, and its assigned to self.response.
+
+        Any exceptions caught are translated and a response object created
+        from them.
+        """
+        result = self._call_converting_errors(callable, args, kwargs)
+        if result is not None:
+            self.response = result
+            self.finished_reading = True
+        # handle unconverted commands
+        if not self._converted_command:
+            self.finished_reading = True
+            if result is None:
+                self.response = SmartServerResponse(('ok',))
+
+    def _call_converting_errors(self, callable, args, kwargs):
+        """Call callable converting errors to Response objects."""
+        try:
+            return callable(*args, **kwargs)
+        except errors.NoSuchFile, e:
+            return SmartServerResponse(('NoSuchFile', e.path))
+        except errors.FileExists, e:
+            return SmartServerResponse(('FileExists', e.path))
+        except errors.DirectoryNotEmpty, e:
+            return SmartServerResponse(('DirectoryNotEmpty', e.path))
+        except errors.ShortReadvError, e:
+            return SmartServerResponse(('ShortReadvError',
+                e.path, str(e.offset), str(e.length), str(e.actual)))
+        except UnicodeError, e:
+            # If it is a DecodeError, than most likely we are starting
+            # with a plain string
+            str_or_unicode = e.object
+            if isinstance(str_or_unicode, unicode):
+                # XXX: UTF-8 might have \x01 (our seperator byte) in it.  We
+                # should escape it somehow.
+                val = 'u:' + str_or_unicode.encode('utf-8')
+            else:
+                val = 's:' + str_or_unicode.encode('base64')
+            # This handles UnicodeEncodeError or UnicodeDecodeError
+            return SmartServerResponse((e.__class__.__name__,
+                    e.encoding, val, str(e.start), str(e.end), e.reason))
+        except errors.TransportNotPossible, e:
+            if e.msg == "readonly transport":
+                return SmartServerResponse(('ReadOnlyError', ))
+            else:
+                raise
+
+

=== added file bzrlib/smart/server.py // file-id:server.py-20061110062051-chzu1
... 0y32vx8gvur-1 // last-changed:andrew.bennetts at canonical.com-20070409044955-
... h3ijql5cvqxia4d4
--- /dev/null
+++ bzrlib/smart/server.py
@@ -0,0 +1,139 @@
+# Copyright (C) 2006, 2007 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
+
+"""Server for smart-server protocol."""
+
+import socket
+import os
+import threading
+
+from bzrlib.smart import medium
+from bzrlib import (
+    trace,
+    transport,
+    urlutils,
+)
+from bzrlib.smart.medium import SmartServerSocketStreamMedium
+
+
+class SmartTCPServer(object):
+    """Listens on a TCP socket and accepts connections from smart clients"""
+
+    def __init__(self, backing_transport, host='127.0.0.1', port=0):
+        """Construct a new server.
+
+        To actually start it running, call either start_background_thread or
+        serve.
+
+        :param host: Name of the interface to listen on.
+        :param port: TCP port to listen on, or 0 to allocate a transient port.
+        """
+        self._server_socket = socket.socket()
+        self._server_socket.bind((host, port))
+        self.port = self._server_socket.getsockname()[1]
+        self._server_socket.listen(1)
+        self._server_socket.settimeout(1)
+        self.backing_transport = backing_transport
+
+    def serve(self):
+        # let connections timeout so that we get a chance to terminate
+        # Keep a reference to the exceptions we want to catch because the socket
+        # module's globals get set to None during interpreter shutdown.
+        from socket import timeout as socket_timeout
+        from socket import error as socket_error
+        self._should_terminate = False
+        while not self._should_terminate:
+            try:
+                self.accept_and_serve()
+            except socket_timeout:
+                # just check if we're asked to stop
+                pass
+            except socket_error, e:
+                trace.warning("client disconnected: %s", e)
+                pass
+
+    def get_url(self):
+        """Return the url of the server"""
+        return "bzr://%s:%d/" % self._server_socket.getsockname()
+
+    def accept_and_serve(self):
+        conn, client_addr = self._server_socket.accept()
+        # For WIN32, where the timeout value from the listening socket
+        # propogates to the newly accepted socket.
+        conn.setblocking(True)
+        conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+        handler = SmartServerSocketStreamMedium(conn, self.backing_transport)
+        connection_thread = threading.Thread(None, handler.serve, name='smart-server-child')
+        connection_thread.setDaemon(True)
+        connection_thread.start()
+
+    def start_background_thread(self):
+        self._server_thread = threading.Thread(None,
+                self.serve,
+                name='server-' + self.get_url())
+        self._server_thread.setDaemon(True)
+        self._server_thread.start()
+
+    def stop_background_thread(self):
+        self._should_terminate = True
+        # At one point we would wait to join the threads here, but it looks
+        # like they don't actually exit.  So now we just leave them running
+        # and expect to terminate the process. -- mbp 20070215
+        # self._server_socket.close()
+        ## sys.stderr.write("waiting for server thread to finish...")
+        ## self._server_thread.join()
+
+
+class SmartTCPServer_for_testing(SmartTCPServer):
+    """Server suitable for use by transport tests.
+    
+    This server is backed by the process's cwd.
+    """
+
+    def __init__(self):
+        self._homedir = urlutils.local_path_to_url(os.getcwd())[7:]
+        # The server is set up by default like for ssh access: the client
+        # passes filesystem-absolute paths; therefore the server must look
+        # them up relative to the root directory.  it might be better to act
+        # a public server and have the server rewrite paths into the test
+        # directory.
+        SmartTCPServer.__init__(self,
+            transport.get_transport(urlutils.local_path_to_url('/')))
+        
+    def get_backing_transport(self, backing_transport_server):
+        """Get a backing transport from a server we are decorating."""
+        return transport.get_transport(backing_transport_server.get_url())
+
+    def setUp(self, backing_transport_server=None):
+        """Set up server for testing"""
+        from bzrlib.transport.chroot import TestingChrootServer
+        if backing_transport_server is None:
+            from bzrlib.transport.local import LocalURLServer
+            backing_transport_server = LocalURLServer()
+        self.chroot_server = TestingChrootServer()
+        self.chroot_server.setUp(backing_transport_server)
+        self.backing_transport = transport.get_transport(
+            self.chroot_server.get_url())
+        self.start_background_thread()
+
+    def tearDown(self):
+        self.stop_background_thread()
+
+    def get_bogus_url(self):
+        """Return a URL which will fail to connect"""
+        return 'bzr://127.0.0.1:1/'
+
+

=== renamed file bzrlib/transport/smart.py // bzrlib/transport/remote.py // las
... t-changed:andrew.bennetts at canonical.com-20070409044955-h3ijql5cvqxia4d4
--- bzrlib/transport/smart.py
+++ bzrlib/transport/remote.py
@@ -14,209 +14,16 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-"""Smart-server protocol, client and server.
-
-Requests are sent as a command and list of arguments, followed by optional
-bulk body data.  Responses are similarly a response and list of arguments,
-followed by bulk body data. ::
-
-  SEP := '\001'
-    Fields are separated by Ctrl-A.
-  BULK_DATA := CHUNK TRAILER
-    Chunks can be repeated as many times as necessary.
-  CHUNK := CHUNK_LEN CHUNK_BODY
-  CHUNK_LEN := DIGIT+ NEWLINE
-    Gives the number of bytes in the following chunk.
-  CHUNK_BODY := BYTE[chunk_len]
-  TRAILER := SUCCESS_TRAILER | ERROR_TRAILER
-  SUCCESS_TRAILER := 'done' NEWLINE
-  ERROR_TRAILER := 
-
-Paths are passed across the network.  The client needs to see a namespace that
-includes any repository that might need to be referenced, and the client needs
-to know about a root directory beyond which it cannot ascend.
-
-Servers run over ssh will typically want to be able to access any path the user 
-can access.  Public servers on the other hand (which might be over http, ssh
-or tcp) will typically want to restrict access to only a particular directory 
-and its children, so will want to do a software virtual root at that level.
-In other words they'll want to rewrite incoming paths to be under that level
-(and prevent escaping using ../ tricks.)
-
-URLs that include ~ should probably be passed across to the server verbatim
-and the server can expand them.  This will proably not be meaningful when 
-limited to a directory?
-
-At the bottom level socket, pipes, HTTP server.  For sockets, we have the idea
-that you have multiple requests and get a read error because the other side did
-shutdown.  For pipes we have read pipe which will have a zero read which marks
-end-of-file.  For HTTP server environment there is not end-of-stream because
-each request coming into the server is independent.
-
-So we need a wrapper around pipes and sockets to seperate out requests from
-substrate and this will give us a single model which is consist for HTTP,
-sockets and pipes.
-
-Server-side
------------
-
- MEDIUM  (factory for protocol, reads bytes & pushes to protocol,
-          uses protocol to detect end-of-request, sends written
-          bytes to client) e.g. socket, pipe, HTTP request handler.
-  ^
-  | bytes.
-  v
-
-PROTOCOL  (serialization, deserialization)  accepts bytes for one
-          request, decodes according to internal state, pushes
-          structured data to handler.  accepts structured data from
-          handler and encodes and writes to the medium.  factory for
-          handler.
-  ^
-  | structured data
-  v
-
-HANDLER   (domain logic) accepts structured data, operates state
-          machine until the request can be satisfied,
-          sends structured data to the protocol.
-
-
-Client-side
------------
-
- CLIENT             domain logic, accepts domain requests, generated structured
-                    data, reads structured data from responses and turns into
-                    domain data.  Sends structured data to the protocol.
-                    Operates state machines until the request can be delivered
-                    (e.g. reading from a bundle generated in bzrlib to deliver a
-                    complete request).
-
-                    Possibly this should just be RemoteBzrDir, RemoteTransport,
-                    ...
-  ^
-  | structured data
-  v
-
-PROTOCOL  (serialization, deserialization)  accepts structured data for one
-          request, encodes and writes to the medium.  Reads bytes from the
-          medium, decodes and allows the client to read structured data.
-  ^
-  | bytes.
-  v
-
- MEDIUM  (accepts bytes from the protocol & delivers to the remote server.
-          Allows the potocol to read bytes e.g. socket, pipe, HTTP request.
-"""
-
-
-# TODO: _translate_error should be on the client, not the transport because
-#     error coding is wire protocol specific.
-
-# TODO: A plain integer from query_version is too simple; should give some
-# capabilities too?
-
-# TODO: Server should probably catch exceptions within itself and send them
-# back across the network.  (But shouldn't catch KeyboardInterrupt etc)
-# Also needs to somehow report protocol errors like bad requests.  Need to
-# consider how we'll handle error reporting, e.g. if we get halfway through a
-# bulk transfer and then something goes wrong.
-
-# TODO: Standard marker at start of request/response lines?
-
-# TODO: Make each request and response self-validatable, e.g. with checksums.
-#
-# TODO: get/put objects could be changed to gradually read back the data as it
-# comes across the network
-#
-# TODO: What should the server do if it hits an error and has to terminate?
-#
-# TODO: is it useful to allow multiple chunks in the bulk data?
-#
-# TODO: If we get an exception during transmission of bulk data we can't just
-# emit the exception because it won't be seen.
-#   John proposes:  I think it would be worthwhile to have a header on each
-#   chunk, that indicates it is another chunk. Then you can send an 'error'
-#   chunk as long as you finish the previous chunk.
-#
-# TODO: Clone method on Transport; should work up towards parent directory;
-# unclear how this should be stored or communicated to the server... maybe
-# just pass it on all relevant requests?
-#
-# TODO: Better name than clone() for changing between directories.  How about
-# open_dir or change_dir or chdir?
-#
-# TODO: Is it really good to have the notion of current directory within the
-# connection?  Perhaps all Transports should factor out a common connection
-# from the thing that has the directory context?
-#
-# TODO: Pull more things common to sftp and ssh to a higher level.
-#
-# TODO: The server that manages a connection should be quite small and retain
-# minimum state because each of the requests are supposed to be stateless.
-# Then we can write another implementation that maps to http.
-#
-# TODO: What to do when a client connection is garbage collected?  Maybe just
-# abruptly drop the connection?
-#
-# TODO: Server in some cases will need to restrict access to files outside of
-# a particular root directory.  LocalTransport doesn't do anything to stop you
-# ascending above the base directory, so we need to prevent paths
-# containing '..' in either the server or transport layers.  (Also need to
-# consider what happens if someone creates a symlink pointing outside the 
-# directory tree...)
-#
-# TODO: Server should rebase absolute paths coming across the network to put
-# them under the virtual root, if one is in use.  LocalTransport currently
-# doesn't do that; if you give it an absolute path it just uses it.
-# 
-# XXX: Arguments can't contain newlines or ascii; possibly we should e.g.
-# urlescape them instead.  Indeed possibly this should just literally be
-# http-over-ssh.
-#
-# FIXME: This transport, with several others, has imperfect handling of paths
-# within urls.  It'd probably be better for ".." from a root to raise an error
-# rather than return the same directory as we do at present.
-#
-# TODO: Rather than working at the Transport layer we want a Branch,
-# Repository or BzrDir objects that talk to a server.
-#
-# TODO: Probably want some way for server commands to gradually produce body
-# data rather than passing it as a string; they could perhaps pass an
-# iterator-like callback that will gradually yield data; it probably needs a
-# close() method that will always be closed to do any necessary cleanup.
-#
-# TODO: Split the actual smart server from the ssh encoding of it.
-#
-# TODO: Perhaps support file-level readwrite operations over the transport
-# too.
-#
-# TODO: SmartBzrDir class, proxying all Branch etc methods across to another
-# branch doing file-level operations.
-#
-
 from cStringIO import StringIO
-import os
-import socket
-import sys
-import tempfile
-import threading
 import urllib
 import urlparse
 
 from bzrlib import (
-    bzrdir,
     errors,
-    revision,
     transport,
-    trace,
-    urlutils,
     )
-from bzrlib.bundle.serializer import write_bundle
-try:
-    from bzrlib.transport import ssh
-except errors.ParamikoNotPresent:
-    # no paramiko.  SmartSSHClientMedium will break.
-    pass
+from bzrlib.smart.protocol import SmartClientRequestProtocolOne
+from bzrlib.smart.medium import SmartTCPClientMedium, SmartSSHClientMedium
 
 # must do this otherwise urllib can't parse the urls properly :(
 for scheme in ['ssh', 'bzr', 'bzr+loopback', 'bzr+ssh', 'bzr+http']:
@@ -228,705 +35,6 @@
 BZR_DEFAULT_PORT = 4155
 
 
-def _recv_tuple(from_file):
-    req_line = from_file.readline()
-    return _decode_tuple(req_line)
-
-
-def _decode_tuple(req_line):
-    if req_line == None or req_line == '':
-        return None
-    if req_line[-1] != '\n':
-        raise errors.SmartProtocolError("request %r not terminated" % req_line)
-    return tuple(req_line[:-1].split('\x01'))
-
-
-def _encode_tuple(args):
-    """Encode the tuple args to a bytestream."""
-    return '\x01'.join(args) + '\n'
-
-
-class SmartProtocolBase(object):
-    """Methods common to client and server"""
-
-    # TODO: this only actually accomodates a single block; possibly should
-    # support multiple chunks?
-    def _encode_bulk_data(self, body):
-        """Encode body as a bulk data chunk."""
-        return ''.join(('%d\n' % len(body), body, 'done\n'))
-
-    def _serialise_offsets(self, offsets):
-        """Serialise a readv offset list."""
-        txt = []
-        for start, length in offsets:
-            txt.append('%d,%d' % (start, length))
-        return '\n'.join(txt)
-        
-
-class SmartServerRequestProtocolOne(SmartProtocolBase):
-    """Server-side encoding and decoding logic for smart version 1."""
-    
-    def __init__(self, backing_transport, write_func):
-        self._backing_transport = backing_transport
-        self.excess_buffer = ''
-        self._finished = False
-        self.in_buffer = ''
-        self.has_dispatched = False
-        self.request = None
-        self._body_decoder = None
-        self._write_func = write_func
-
-    def accept_bytes(self, bytes):
-        """Take bytes, and advance the internal state machine appropriately.
-        
-        :param bytes: must be a byte string
-        """
-        assert isinstance(bytes, str)
-        self.in_buffer += bytes
-        if not self.has_dispatched:
-            if '\n' not in self.in_buffer:
-                # no command line yet
-                return
-            self.has_dispatched = True
-            try:
-                first_line, self.in_buffer = self.in_buffer.split('\n', 1)
-                first_line += '\n'
-                req_args = _decode_tuple(first_line)
-                self.request = SmartServerRequestHandler(
-                    self._backing_transport)
-                self.request.dispatch_command(req_args[0], req_args[1:])
-                if self.request.finished_reading:
-                    # trivial request
-                    self.excess_buffer = self.in_buffer
-                    self.in_buffer = ''
-                    self._send_response(self.request.response.args,
-                        self.request.response.body)
-            except KeyboardInterrupt:
-                raise
-            except Exception, exception:
-                # everything else: pass to client, flush, and quit
-                self._send_response(('error', str(exception)))
-                return
-
-        if self.has_dispatched:
-            if self._finished:
-                # nothing to do.XXX: this routine should be a single state 
-                # machine too.
-                self.excess_buffer += self.in_buffer
-                self.in_buffer = ''
-                return
-            if self._body_decoder is None:
-                self._body_decoder = LengthPrefixedBodyDecoder()
-            self._body_decoder.accept_bytes(self.in_buffer)
-            self.in_buffer = self._body_decoder.unused_data
-            body_data = self._body_decoder.read_pending_data()
-            self.request.accept_body(body_data)
-            if self._body_decoder.finished_reading:
-                self.request.end_of_body()
-                assert self.request.finished_reading, \
-                    "no more body, request not finished"
-            if self.request.response is not None:
-                self._send_response(self.request.response.args,
-                    self.request.response.body)
-                self.excess_buffer = self.in_buffer
-                self.in_buffer = ''
-            else:
-                assert not self.request.finished_reading, \
-                    "no response and we have finished reading."
-
-    def _send_response(self, args, body=None):
-        """Send a smart server response down the output stream."""
-        assert not self._finished, 'response already sent'
-        self._finished = True
-        self._write_func(_encode_tuple(args))
-        if body is not None:
-            assert isinstance(body, str), 'body must be a str'
-            bytes = self._encode_bulk_data(body)
-            self._write_func(bytes)
-
-    def next_read_size(self):
-        if self._finished:
-            return 0
-        if self._body_decoder is None:
-            return 1
-        else:
-            return self._body_decoder.next_read_size()
-
-
-class LengthPrefixedBodyDecoder(object):
-    """Decodes the length-prefixed bulk data."""
-    
-    def __init__(self):
-        self.bytes_left = None
-        self.finished_reading = False
-        self.unused_data = ''
-        self.state_accept = self._state_accept_expecting_length
-        self.state_read = self._state_read_no_data
-        self._in_buffer = ''
-        self._trailer_buffer = ''
-    
-    def accept_bytes(self, bytes):
-        """Decode as much of bytes as possible.
-
-        If 'bytes' contains too much data it will be appended to
-        self.unused_data.
-
-        finished_reading will be set when no more data is required.  Further
-        data will be appended to self.unused_data.
-        """
-        # accept_bytes is allowed to change the state
-        current_state = self.state_accept
-        self.state_accept(bytes)
-        while current_state != self.state_accept:
-            current_state = self.state_accept
-            self.state_accept('')
-
-    def next_read_size(self):
-        if self.bytes_left is not None:
-            # Ideally we want to read all the remainder of the body and the
-            # trailer in one go.
-            return self.bytes_left + 5
-        elif self.state_accept == self._state_accept_reading_trailer:
-            # Just the trailer left
-            return 5 - len(self._trailer_buffer)
-        elif self.state_accept == self._state_accept_expecting_length:
-            # There's still at least 6 bytes left ('\n' to end the length, plus
-            # 'done\n').
-            return 6
-        else:
-            # Reading excess data.  Either way, 1 byte at a time is fine.
-            return 1
-        
-    def read_pending_data(self):
-        """Return any pending data that has been decoded."""
-        return self.state_read()
-
-    def _state_accept_expecting_length(self, bytes):
-        self._in_buffer += bytes
-        pos = self._in_buffer.find('\n')
-        if pos == -1:
-            return
-        self.bytes_left = int(self._in_buffer[:pos])
-        self._in_buffer = self._in_buffer[pos+1:]
-        self.bytes_left -= len(self._in_buffer)
-        self.state_accept = self._state_accept_reading_body
-        self.state_read = self._state_read_in_buffer
-
-    def _state_accept_reading_body(self, bytes):
-        self._in_buffer += bytes
-        self.bytes_left -= len(bytes)
-        if self.bytes_left <= 0:
-            # Finished with body
-            if self.bytes_left != 0:
-                self._trailer_buffer = self._in_buffer[self.bytes_left:]
-                self._in_buffer = self._in_buffer[:self.bytes_left]
-            self.bytes_left = None
-            self.state_accept = self._state_accept_reading_trailer
-        
-    def _state_accept_reading_trailer(self, bytes):
-        self._trailer_buffer += bytes
-        # TODO: what if the trailer does not match "done\n"?  Should this raise
-        # a ProtocolViolation exception?
-        if self._trailer_buffer.startswith('done\n'):
-            self.unused_data = self._trailer_buffer[len('done\n'):]
-            self.state_accept = self._state_accept_reading_unused
-            self.finished_reading = True
-    
-    def _state_accept_reading_unused(self, bytes):
-        self.unused_data += bytes
-
-    def _state_read_no_data(self):
-        return ''
-
-    def _state_read_in_buffer(self):
-        result = self._in_buffer
-        self._in_buffer = ''
-        return result
-
-
-class SmartServerStreamMedium(object):
-    """Handles smart commands coming over a stream.
-
-    The stream may be a pipe connected to sshd, or a tcp socket, or an
-    in-process fifo for testing.
-
-    One instance is created for each connected client; it can serve multiple
-    requests in the lifetime of the connection.
-
-    The server passes requests through to an underlying backing transport, 
-    which will typically be a LocalTransport looking at the server's filesystem.
-    """
-
-    def __init__(self, backing_transport):
-        """Construct new server.
-
-        :param backing_transport: Transport for the directory served.
-        """
-        # backing_transport could be passed to serve instead of __init__
-        self.backing_transport = backing_transport
-        self.finished = False
-
-    def serve(self):
-        """Serve requests until the client disconnects."""
-        # Keep a reference to stderr because the sys module's globals get set to
-        # None during interpreter shutdown.
-        from sys import stderr
-        try:
-            while not self.finished:
-                protocol = SmartServerRequestProtocolOne(self.backing_transport,
-                                                         self._write_out)
-                self._serve_one_request(protocol)
-        except Exception, e:
-            stderr.write("%s terminating on exception %s\n" % (self, e))
-            raise
-
-    def _serve_one_request(self, protocol):
-        """Read one request from input, process, send back a response.
-        
-        :param protocol: a SmartServerRequestProtocol.
-        """
-        try:
-            self._serve_one_request_unguarded(protocol)
-        except KeyboardInterrupt:
-            raise
-        except Exception, e:
-            self.terminate_due_to_error()
-
-    def terminate_due_to_error(self):
-        """Called when an unhandled exception from the protocol occurs."""
-        raise NotImplementedError(self.terminate_due_to_error)
-
-
-class SmartServerSocketStreamMedium(SmartServerStreamMedium):
-
-    def __init__(self, sock, backing_transport):
-        """Constructor.
-
-        :param sock: the socket the server will read from.  It will be put
-            into blocking mode.
-        """
-        SmartServerStreamMedium.__init__(self, backing_transport)
-        self.push_back = ''
-        sock.setblocking(True)
-        self.socket = sock
-
-    def _serve_one_request_unguarded(self, protocol):
-        while protocol.next_read_size():
-            if self.push_back:
-                protocol.accept_bytes(self.push_back)
-                self.push_back = ''
-            else:
-                bytes = self.socket.recv(4096)
-                if bytes == '':
-                    self.finished = True
-                    return
-                protocol.accept_bytes(bytes)
-        
-        self.push_back = protocol.excess_buffer
-    
-    def terminate_due_to_error(self):
-        """Called when an unhandled exception from the protocol occurs."""
-        # TODO: This should log to a server log file, but no such thing
-        # exists yet.  Andrew Bennetts 2006-09-29.
-        self.socket.close()
-        self.finished = True
-
-    def _write_out(self, bytes):
-        self.socket.sendall(bytes)
-
-
-class SmartServerPipeStreamMedium(SmartServerStreamMedium):
-
-    def __init__(self, in_file, out_file, backing_transport):
-        """Construct new server.
-
-        :param in_file: Python file from which requests can be read.
-        :param out_file: Python file to write responses.
-        :param backing_transport: Transport for the directory served.
-        """
-        SmartServerStreamMedium.__init__(self, backing_transport)
-        if sys.platform == 'win32':
-            # force binary mode for files
-            import msvcrt
-            for f in (in_file, out_file):
-                fileno = getattr(f, 'fileno', None)
-                if fileno:
-                    msvcrt.setmode(fileno(), os.O_BINARY)
-        self._in = in_file
-        self._out = out_file
-
-    def _serve_one_request_unguarded(self, protocol):
-        while True:
-            bytes_to_read = protocol.next_read_size()
-            if bytes_to_read == 0:
-                # Finished serving this request.
-                self._out.flush()
-                return
-            bytes = self._in.read(bytes_to_read)
-            if bytes == '':
-                # Connection has been closed.
-                self.finished = True
-                self._out.flush()
-                return
-            protocol.accept_bytes(bytes)
-
-    def terminate_due_to_error(self):
-        # TODO: This should log to a server log file, but no such thing
-        # exists yet.  Andrew Bennetts 2006-09-29.
-        self._out.close()
-        self.finished = True
-
-    def _write_out(self, bytes):
-        self._out.write(bytes)
-
-
-class SmartServerResponse(object):
-    """Response generated by SmartServerRequestHandler."""
-
-    def __init__(self, args, body=None):
-        self.args = args
-        self.body = body
-
-# XXX: TODO: Create a SmartServerRequestHandler which will take the responsibility
-# for delivering the data for a request. This could be done with as the
-# StreamServer, though that would create conflation between request and response
-# which may be undesirable.
-
-
-class SmartServerRequestHandler(object):
-    """Protocol logic for smart server.
-    
-    This doesn't handle serialization at all, it just processes requests and
-    creates responses.
-    """
-
-    # IMPORTANT FOR IMPLEMENTORS: It is important that SmartServerRequestHandler
-    # not contain encoding or decoding logic to allow the wire protocol to vary
-    # from the object protocol: we will want to tweak the wire protocol separate
-    # from the object model, and ideally we will be able to do that without
-    # having a SmartServerRequestHandler subclass for each wire protocol, rather
-    # just a Protocol subclass.
-
-    # TODO: Better way of representing the body for commands that take it,
-    # and allow it to be streamed into the server.
-    
-    def __init__(self, backing_transport):
-        self._backing_transport = backing_transport
-        self._converted_command = False
-        self.finished_reading = False
-        self._body_bytes = ''
-        self.response = None
-
-    def accept_body(self, bytes):
-        """Accept body data.
-
-        This should be overriden for each command that desired body data to
-        handle the right format of that data. I.e. plain bytes, a bundle etc.
-
-        The deserialisation into that format should be done in the Protocol
-        object. Set self.desired_body_format to the format your method will
-        handle.
-        """
-        # default fallback is to accumulate bytes.
-        self._body_bytes += bytes
-        
-    def _end_of_body_handler(self):
-        """An unimplemented end of body handler."""
-        raise NotImplementedError(self._end_of_body_handler)
-        
-    def do_hello(self):
-        """Answer a version request with my version."""
-        return SmartServerResponse(('ok', '1'))
-
-    def do_has(self, relpath):
-        r = self._backing_transport.has(relpath) and 'yes' or 'no'
-        return SmartServerResponse((r,))
-
-    def do_get(self, relpath):
-        backing_bytes = self._backing_transport.get_bytes(relpath)
-        return SmartServerResponse(('ok',), backing_bytes)
-
-    def _deserialise_optional_mode(self, mode):
-        # XXX: FIXME this should be on the protocol object.
-        if mode == '':
-            return None
-        else:
-            return int(mode)
-
-    def do_append(self, relpath, mode):
-        self._converted_command = True
-        self._relpath = relpath
-        self._mode = self._deserialise_optional_mode(mode)
-        self._end_of_body_handler = self._handle_do_append_end
-    
-    def _handle_do_append_end(self):
-        old_length = self._backing_transport.append_bytes(
-            self._relpath, self._body_bytes, self._mode)
-        self.response = SmartServerResponse(('appended', '%d' % old_length))
-
-    def do_delete(self, relpath):
-        self._backing_transport.delete(relpath)
-
-    def do_iter_files_recursive(self, relpath):
-        transport = self._backing_transport.clone(relpath)
-        filenames = transport.iter_files_recursive()
-        return SmartServerResponse(('names',) + tuple(filenames))
-
-    def do_list_dir(self, relpath):
-        filenames = self._backing_transport.list_dir(relpath)
-        return SmartServerResponse(('names',) + tuple(filenames))
-
-    def do_mkdir(self, relpath, mode):
-        self._backing_transport.mkdir(relpath,
-                                      self._deserialise_optional_mode(mode))
-
-    def do_move(self, rel_from, rel_to):
-        self._backing_transport.move(rel_from, rel_to)
-
-    def do_put(self, relpath, mode):
-        self._converted_command = True
-        self._relpath = relpath
-        self._mode = self._deserialise_optional_mode(mode)
-        self._end_of_body_handler = self._handle_do_put
-
-    def _handle_do_put(self):
-        self._backing_transport.put_bytes(self._relpath,
-                self._body_bytes, self._mode)
-        self.response = SmartServerResponse(('ok',))
-
-    def _deserialise_offsets(self, text):
-        # XXX: FIXME this should be on the protocol object.
-        offsets = []
-        for line in text.split('\n'):
-            if not line:
-                continue
-            start, length = line.split(',')
-            offsets.append((int(start), int(length)))
-        return offsets
-
-    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._dir_mode = self._deserialise_optional_mode(dir_mode)
-        self._mode = self._deserialise_optional_mode(mode)
-        # a boolean would be nicer XXX
-        self._create_parent = (create_parent == 'T')
-
-    def _handle_put_non_atomic(self):
-        self._backing_transport.put_bytes_non_atomic(self._relpath,
-                self._body_bytes,
-                mode=self._mode,
-                create_parent_dir=self._create_parent,
-                dir_mode=self._dir_mode)
-        self.response = SmartServerResponse(('ok',))
-
-    def do_readv(self, relpath):
-        self._converted_command = True
-        self._end_of_body_handler = self._handle_readv_offsets
-        self._relpath = relpath
-
-    def end_of_body(self):
-        """No more body data will be received."""
-        self._run_handler_code(self._end_of_body_handler, (), {})
-        # cannot read after this.
-        self.finished_reading = True
-
-    def _handle_readv_offsets(self):
-        """accept offsets for a readv request."""
-        offsets = self._deserialise_offsets(self._body_bytes)
-        backing_bytes = ''.join(bytes for offset, bytes in
-            self._backing_transport.readv(self._relpath, offsets))
-        self.response = SmartServerResponse(('readv',), backing_bytes)
-        
-    def do_rename(self, rel_from, rel_to):
-        self._backing_transport.rename(rel_from, rel_to)
-
-    def do_rmdir(self, relpath):
-        self._backing_transport.rmdir(relpath)
-
-    def do_stat(self, relpath):
-        stat = self._backing_transport.stat(relpath)
-        return SmartServerResponse(('stat', str(stat.st_size), oct(stat.st_mode)))
-        
-    def do_get_bundle(self, path, revision_id):
-        # open transport relative to our base
-        t = self._backing_transport.clone(path)
-        control, extra_path = bzrdir.BzrDir.open_containing_from_transport(t)
-        repo = control.open_repository()
-        tmpf = tempfile.TemporaryFile()
-        base_revision = revision.NULL_REVISION
-        write_bundle(repo, revision_id, base_revision, tmpf)
-        tmpf.seek(0)
-        return SmartServerResponse((), tmpf.read())
-
-    def dispatch_command(self, cmd, args):
-        """Deprecated compatibility method.""" # XXX XXX
-        func = getattr(self, 'do_' + cmd, None)
-        if func is None:
-            raise errors.SmartProtocolError("bad request %r" % (cmd,))
-        self._run_handler_code(func, args, {})
-
-    def _run_handler_code(self, callable, args, kwargs):
-        """Run some handler specific code 'callable'.
-
-        If a result is returned, it is considered to be the commands response,
-        and finished_reading is set true, and its assigned to self.response.
-
-        Any exceptions caught are translated and a response object created
-        from them.
-        """
-        result = self._call_converting_errors(callable, args, kwargs)
-        if result is not None:
-            self.response = result
-            self.finished_reading = True
-        # handle unconverted commands
-        if not self._converted_command:
-            self.finished_reading = True
-            if result is None:
-                self.response = SmartServerResponse(('ok',))
-
-    def _call_converting_errors(self, callable, args, kwargs):
-        """Call callable converting errors to Response objects."""
-        try:
-            return callable(*args, **kwargs)
-        except errors.NoSuchFile, e:
-            return SmartServerResponse(('NoSuchFile', e.path))
-        except errors.FileExists, e:
-            return SmartServerResponse(('FileExists', e.path))
-        except errors.DirectoryNotEmpty, e:
-            return SmartServerResponse(('DirectoryNotEmpty', e.path))
-        except errors.ShortReadvError, e:
-            return SmartServerResponse(('ShortReadvError',
-                e.path, str(e.offset), str(e.length), str(e.actual)))
-        except UnicodeError, e:
-            # If it is a DecodeError, than most likely we are starting
-            # with a plain string
-            str_or_unicode = e.object
-            if isinstance(str_or_unicode, unicode):
-                # XXX: UTF-8 might have \x01 (our seperator byte) in it.  We
-                # should escape it somehow.
-                val = 'u:' + str_or_unicode.encode('utf-8')
-            else:
-                val = 's:' + str_or_unicode.encode('base64')
-            # This handles UnicodeEncodeError or UnicodeDecodeError
-            return SmartServerResponse((e.__class__.__name__,
-                    e.encoding, val, str(e.start), str(e.end), e.reason))
-        except errors.TransportNotPossible, e:
-            if e.msg == "readonly transport":
-                return SmartServerResponse(('ReadOnlyError', ))
-            else:
-                raise
-
-
-class SmartTCPServer(object):
-    """Listens on a TCP socket and accepts connections from smart clients"""
-
-    def __init__(self, backing_transport, host='127.0.0.1', port=0):
-        """Construct a new server.
-
-        To actually start it running, call either start_background_thread or
-        serve.
-
-        :param host: Name of the interface to listen on.
-        :param port: TCP port to listen on, or 0 to allocate a transient port.
-        """
-        self._server_socket = socket.socket()
-        self._server_socket.bind((host, port))
-        self.port = self._server_socket.getsockname()[1]
-        self._server_socket.listen(1)
-        self._server_socket.settimeout(1)
-        self.backing_transport = backing_transport
-
-    def serve(self):
-        # let connections timeout so that we get a chance to terminate
-        # Keep a reference to the exceptions we want to catch because the socket
-        # module's globals get set to None during interpreter shutdown.
-        from socket import timeout as socket_timeout
-        from socket import error as socket_error
-        self._should_terminate = False
-        while not self._should_terminate:
-            try:
-                self.accept_and_serve()
-            except socket_timeout:
-                # just check if we're asked to stop
-                pass
-            except socket_error, e:
-                trace.warning("client disconnected: %s", e)
-                pass
-
-    def get_url(self):
-        """Return the url of the server"""
-        return "bzr://%s:%d/" % self._server_socket.getsockname()
-
-    def accept_and_serve(self):
-        conn, client_addr = self._server_socket.accept()
-        # For WIN32, where the timeout value from the listening socket
-        # propogates to the newly accepted socket.
-        conn.setblocking(True)
-        conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-        handler = SmartServerSocketStreamMedium(conn, self.backing_transport)
-        connection_thread = threading.Thread(None, handler.serve, name='smart-server-child')
-        connection_thread.setDaemon(True)
-        connection_thread.start()
-
-    def start_background_thread(self):
-        self._server_thread = threading.Thread(None,
-                self.serve,
-                name='server-' + self.get_url())
-        self._server_thread.setDaemon(True)
-        self._server_thread.start()
-
-    def stop_background_thread(self):
-        self._should_terminate = True
-        # At one point we would wait to join the threads here, but it looks
-        # like they don't actually exit.  So now we just leave them running
-        # and expect to terminate the process. -- mbp 20070215
-        # self._server_socket.close()
-        ## sys.stderr.write("waiting for server thread to finish...")
-        ## self._server_thread.join()
-
-
-class SmartTCPServer_for_testing(SmartTCPServer):
-    """Server suitable for use by transport tests.
-    
-    This server is backed by the process's cwd.
-    """
-
-    def __init__(self):
-        self._homedir = urlutils.local_path_to_url(os.getcwd())[7:]
-        # The server is set up by default like for ssh access: the client
-        # passes filesystem-absolute paths; therefore the server must look
-        # them up relative to the root directory.  it might be better to act
-        # a public server and have the server rewrite paths into the test
-        # directory.
-        SmartTCPServer.__init__(self,
-            transport.get_transport(urlutils.local_path_to_url('/')))
-        
-    def get_backing_transport(self, backing_transport_server):
-        """Get a backing transport from a server we are decorating."""
-        return transport.get_transport(backing_transport_server.get_url())
-
-    def setUp(self, backing_transport_server=None):
-        """Set up server for testing"""
-        from bzrlib.transport.chroot import TestingChrootServer
-        if backing_transport_server is None:
-            from bzrlib.transport.local import LocalURLServer
-            backing_transport_server = LocalURLServer()
-        self.chroot_server = TestingChrootServer()
-        self.chroot_server.setUp(backing_transport_server)
-        self.backing_transport = transport.get_transport(
-            self.chroot_server.get_url())
-        self.start_background_thread()
-
-    def tearDown(self):
-        self.stop_background_thread()
-
-    def get_bogus_url(self):
-        """Return a URL which will fail to connect"""
-        return 'bzr://127.0.0.1:1/'
-
-
 class SmartStat(object):
 
     def __init__(self, size, mode):
@@ -1290,455 +398,6 @@
             self._translate_error(resp)
 
 
-class SmartClientMediumRequest(object):
-    """A request on a SmartClientMedium.
-
-    Each request allows bytes to be provided to it via accept_bytes, and then
-    the response bytes to be read via read_bytes.
-
-    For instance:
-    request.accept_bytes('123')
-    request.finished_writing()
-    result = request.read_bytes(3)
-    request.finished_reading()
-
-    It is up to the individual SmartClientMedium whether multiple concurrent
-    requests can exist. See SmartClientMedium.get_request to obtain instances 
-    of SmartClientMediumRequest, and the concrete Medium you are using for 
-    details on concurrency and pipelining.
-    """
-
-    def __init__(self, medium):
-        """Construct a SmartClientMediumRequest for the medium medium."""
-        self._medium = medium
-        # we track state by constants - we may want to use the same
-        # pattern as BodyReader if it gets more complex.
-        # valid states are: "writing", "reading", "done"
-        self._state = "writing"
-
-    def accept_bytes(self, bytes):
-        """Accept bytes for inclusion in this request.
-
-        This method may not be be called after finished_writing() has been
-        called.  It depends upon the Medium whether or not the bytes will be
-        immediately transmitted. Message based Mediums will tend to buffer the
-        bytes until finished_writing() is called.
-
-        :param bytes: A bytestring.
-        """
-        if self._state != "writing":
-            raise errors.WritingCompleted(self)
-        self._accept_bytes(bytes)
-
-    def _accept_bytes(self, bytes):
-        """Helper for accept_bytes.
-
-        Accept_bytes checks the state of the request to determing if bytes
-        should be accepted. After that it hands off to _accept_bytes to do the
-        actual acceptance.
-        """
-        raise NotImplementedError(self._accept_bytes)
-
-    def finished_reading(self):
-        """Inform the request that all desired data has been read.
-
-        This will remove the request from the pipeline for its medium (if the
-        medium supports pipelining) and any further calls to methods on the
-        request will raise ReadingCompleted.
-        """
-        if self._state == "writing":
-            raise errors.WritingNotComplete(self)
-        if self._state != "reading":
-            raise errors.ReadingCompleted(self)
-        self._state = "done"
-        self._finished_reading()
-
-    def _finished_reading(self):
-        """Helper for finished_reading.
-
-        finished_reading checks the state of the request to determine if 
-        finished_reading is allowed, and if it is hands off to _finished_reading
-        to perform the action.
-        """
-        raise NotImplementedError(self._finished_reading)
-
-    def finished_writing(self):
-        """Finish the writing phase of this request.
-
-        This will flush all pending data for this request along the medium.
-        After calling finished_writing, you may not call accept_bytes anymore.
-        """
-        if self._state != "writing":
-            raise errors.WritingCompleted(self)
-        self._state = "reading"
-        self._finished_writing()
-
-    def _finished_writing(self):
-        """Helper for finished_writing.
-
-        finished_writing checks the state of the request to determine if 
-        finished_writing is allowed, and if it is hands off to _finished_writing
-        to perform the action.
-        """
-        raise NotImplementedError(self._finished_writing)
-
-    def read_bytes(self, count):
-        """Read bytes from this requests response.
-
-        This method will block and wait for count bytes to be read. It may not
-        be invoked until finished_writing() has been called - this is to ensure
-        a message-based approach to requests, for compatability with message
-        based mediums like HTTP.
-        """
-        if self._state == "writing":
-            raise errors.WritingNotComplete(self)
-        if self._state != "reading":
-            raise errors.ReadingCompleted(self)
-        return self._read_bytes(count)
-
-    def _read_bytes(self, count):
-        """Helper for read_bytes.
-
-        read_bytes checks the state of the request to determing if bytes
-        should be read. After that it hands off to _read_bytes to do the
-        actual read.
-        """
-        raise NotImplementedError(self._read_bytes)
-
-
-class SmartClientStreamMediumRequest(SmartClientMediumRequest):
-    """A SmartClientMediumRequest that works with an SmartClientStreamMedium."""
-
-    def __init__(self, medium):
-        SmartClientMediumRequest.__init__(self, medium)
-        # check that we are safe concurrency wise. If some streams start
-        # allowing concurrent requests - i.e. via multiplexing - then this
-        # assert should be moved to SmartClientStreamMedium.get_request,
-        # and the setting/unsetting of _current_request likewise moved into
-        # that class : but its unneeded overhead for now. RBC 20060922
-        if self._medium._current_request is not None:
-            raise errors.TooManyConcurrentRequests(self._medium)
-        self._medium._current_request = self
-
-    def _accept_bytes(self, bytes):
-        """See SmartClientMediumRequest._accept_bytes.
-        
-        This forwards to self._medium._accept_bytes because we are operating
-        on the mediums stream.
-        """
-        self._medium._accept_bytes(bytes)
-
-    def _finished_reading(self):
-        """See SmartClientMediumRequest._finished_reading.
-
-        This clears the _current_request on self._medium to allow a new 
-        request to be created.
-        """
-        assert self._medium._current_request is self
-        self._medium._current_request = None
-        
-    def _finished_writing(self):
-        """See SmartClientMediumRequest._finished_writing.
-
-        This invokes self._medium._flush to ensure all bytes are transmitted.
-        """
-        self._medium._flush()
-
-    def _read_bytes(self, count):
-        """See SmartClientMediumRequest._read_bytes.
-        
-        This forwards to self._medium._read_bytes because we are operating
-        on the mediums stream.
-        """
-        return self._medium._read_bytes(count)
-
-
-class SmartClientRequestProtocolOne(SmartProtocolBase):
-    """The client-side protocol for smart version 1."""
-
-    def __init__(self, request):
-        """Construct a SmartClientRequestProtocolOne.
-
-        :param request: A SmartClientMediumRequest to serialise onto and
-            deserialise from.
-        """
-        self._request = request
-        self._body_buffer = None
-
-    def call(self, *args):
-        bytes = _encode_tuple(args)
-        self._request.accept_bytes(bytes)
-        self._request.finished_writing()
-
-    def call_with_body_bytes(self, args, body):
-        """Make a remote call of args with body bytes 'body'.
-
-        After calling this, call read_response_tuple to find the result out.
-        """
-        bytes = _encode_tuple(args)
-        self._request.accept_bytes(bytes)
-        bytes = self._encode_bulk_data(body)
-        self._request.accept_bytes(bytes)
-        self._request.finished_writing()
-
-    def call_with_body_readv_array(self, args, body):
-        """Make a remote call with a readv array.
-
-        The body is encoded with one line per readv offset pair. The numbers in
-        each pair are separated by a comma, and no trailing \n is emitted.
-        """
-        bytes = _encode_tuple(args)
-        self._request.accept_bytes(bytes)
-        readv_bytes = self._serialise_offsets(body)
-        bytes = self._encode_bulk_data(readv_bytes)
-        self._request.accept_bytes(bytes)
-        self._request.finished_writing()
-
-    def cancel_read_body(self):
-        """After expecting a body, a response code may indicate one otherwise.
-
-        This method lets the domain client inform the protocol that no body
-        will be transmitted. This is a terminal method: after calling it the
-        protocol is not able to be used further.
-        """
-        self._request.finished_reading()
-
-    def read_response_tuple(self, expect_body=False):
-        """Read a response tuple from the wire.
-
-        This should only be called once.
-        """
-        result = self._recv_tuple()
-        if not expect_body:
-            self._request.finished_reading()
-        return result
-
-    def read_body_bytes(self, count=-1):
-        """Read bytes from the body, decoding into a byte stream.
-        
-        We read all bytes at once to ensure we've checked the trailer for 
-        errors, and then feed the buffer back as read_body_bytes is called.
-        """
-        if self._body_buffer is not None:
-            return self._body_buffer.read(count)
-        _body_decoder = LengthPrefixedBodyDecoder()
-
-        while not _body_decoder.finished_reading:
-            bytes_wanted = _body_decoder.next_read_size()
-            bytes = self._request.read_bytes(bytes_wanted)
-            _body_decoder.accept_bytes(bytes)
-        self._request.finished_reading()
-        self._body_buffer = StringIO(_body_decoder.read_pending_data())
-        # XXX: TODO check the trailer result.
-        return self._body_buffer.read(count)
-
-    def _recv_tuple(self):
-        """Receive a tuple from the medium request."""
-        line = ''
-        while not line or line[-1] != '\n':
-            # TODO: this is inefficient - but tuples are short.
-            new_char = self._request.read_bytes(1)
-            line += new_char
-            assert new_char != '', "end of file reading from server."
-        return _decode_tuple(line)
-
-    def query_version(self):
-        """Return protocol version number of the server."""
-        self.call('hello')
-        resp = self.read_response_tuple()
-        if resp == ('ok', '1'):
-            return 1
-        else:
-            raise errors.SmartProtocolError("bad response %r" % (resp,))
-
-
-class SmartClientMedium(object):
-    """Smart client is a medium for sending smart protocol requests over."""
-
-    def disconnect(self):
-        """If this medium maintains a persistent connection, close it.
-        
-        The default implementation does nothing.
-        """
-        
-
-class SmartClientStreamMedium(SmartClientMedium):
-    """Stream based medium common class.
-
-    SmartClientStreamMediums operate on a stream. All subclasses use a common
-    SmartClientStreamMediumRequest for their requests, and should implement
-    _accept_bytes and _read_bytes to allow the request objects to send and
-    receive bytes.
-    """
-
-    def __init__(self):
-        self._current_request = None
-
-    def accept_bytes(self, bytes):
-        self._accept_bytes(bytes)
-
-    def __del__(self):
-        """The SmartClientStreamMedium knows how to close the stream when it is
-        finished with it.
-        """
-        self.disconnect()
-
-    def _flush(self):
-        """Flush the output stream.
-        
-        This method is used by the SmartClientStreamMediumRequest to ensure that
-        all data for a request is sent, to avoid long timeouts or deadlocks.
-        """
-        raise NotImplementedError(self._flush)
-
-    def get_request(self):
-        """See SmartClientMedium.get_request().
-
-        SmartClientStreamMedium always returns a SmartClientStreamMediumRequest
-        for get_request.
-        """
-        return SmartClientStreamMediumRequest(self)
-
-    def read_bytes(self, count):
-        return self._read_bytes(count)
-
-
-class SmartSimplePipesClientMedium(SmartClientStreamMedium):
-    """A client medium using simple pipes.
-    
-    This client does not manage the pipes: it assumes they will always be open.
-    """
-
-    def __init__(self, readable_pipe, writeable_pipe):
-        SmartClientStreamMedium.__init__(self)
-        self._readable_pipe = readable_pipe
-        self._writeable_pipe = writeable_pipe
-
-    def _accept_bytes(self, bytes):
-        """See SmartClientStreamMedium.accept_bytes."""
-        self._writeable_pipe.write(bytes)
-
-    def _flush(self):
-        """See SmartClientStreamMedium._flush()."""
-        self._writeable_pipe.flush()
-
-    def _read_bytes(self, count):
-        """See SmartClientStreamMedium._read_bytes."""
-        return self._readable_pipe.read(count)
-
-
-class SmartSSHClientMedium(SmartClientStreamMedium):
-    """A client medium using SSH."""
-    
-    def __init__(self, host, port=None, username=None, password=None,
-            vendor=None):
-        """Creates a client that will connect on the first use.
-        
-        :param vendor: An optional override for the ssh vendor to use. See
-            bzrlib.transport.ssh for details on ssh vendors.
-        """
-        SmartClientStreamMedium.__init__(self)
-        self._connected = False
-        self._host = host
-        self._password = password
-        self._port = port
-        self._username = username
-        self._read_from = None
-        self._ssh_connection = None
-        self._vendor = vendor
-        self._write_to = None
-
-    def _accept_bytes(self, bytes):
-        """See SmartClientStreamMedium.accept_bytes."""
-        self._ensure_connection()
-        self._write_to.write(bytes)
-
-    def disconnect(self):
-        """See SmartClientMedium.disconnect()."""
-        if not self._connected:
-            return
-        self._read_from.close()
-        self._write_to.close()
-        self._ssh_connection.close()
-        self._connected = False
-
-    def _ensure_connection(self):
-        """Connect this medium if not already connected."""
-        if self._connected:
-            return
-        executable = os.environ.get('BZR_REMOTE_PATH', 'bzr')
-        if self._vendor is None:
-            vendor = ssh._get_ssh_vendor()
-        else:
-            vendor = self._vendor
-        self._ssh_connection = vendor.connect_ssh(self._username,
-                self._password, self._host, self._port,
-                command=[executable, 'serve', '--inet', '--directory=/',
-                         '--allow-writes'])
-        self._read_from, self._write_to = \
-            self._ssh_connection.get_filelike_channels()
-        self._connected = True
-
-    def _flush(self):
-        """See SmartClientStreamMedium._flush()."""
-        self._write_to.flush()
-
-    def _read_bytes(self, count):
-        """See SmartClientStreamMedium.read_bytes."""
-        if not self._connected:
-            raise errors.MediumNotConnected(self)
-        return self._read_from.read(count)
-
-
-class SmartTCPClientMedium(SmartClientStreamMedium):
-    """A client medium using TCP."""
-    
-    def __init__(self, host, port):
-        """Creates a client that will connect on the first use."""
-        SmartClientStreamMedium.__init__(self)
-        self._connected = False
-        self._host = host
-        self._port = port
-        self._socket = None
-
-    def _accept_bytes(self, bytes):
-        """See SmartClientMedium.accept_bytes."""
-        self._ensure_connection()
-        self._socket.sendall(bytes)
-
-    def disconnect(self):
-        """See SmartClientMedium.disconnect()."""
-        if not self._connected:
-            return
-        self._socket.close()
-        self._socket = None
-        self._connected = False
-
-    def _ensure_connection(self):
-        """Connect this medium if not already connected."""
-        if self._connected:
-            return
-        self._socket = socket.socket()
-        self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-        result = self._socket.connect_ex((self._host, int(self._port)))
-        if result:
-            raise errors.ConnectionError("failed to connect to %s:%d: %s" %
-                    (self._host, self._port, os.strerror(result)))
-        self._connected = True
-
-    def _flush(self):
-        """See SmartClientStreamMedium._flush().
-        
-        For TCP we do no flushing. We may want to turn off TCP_NODELAY and 
-        add a means to do a flush, but that can be done in the future.
-        """
-
-    def _read_bytes(self, count):
-        """See SmartClientMedium.read_bytes."""
-        if not self._connected:
-            raise errors.MediumNotConnected(self)
-        return self._socket.recv(count)
-
 
 class SmartTCPTransport(SmartTransport):
     """Connection to smart server over plain tcp.
@@ -1838,6 +497,7 @@
 
 def get_test_permutations():
     """Return (transport, server) permutations for testing."""
+    from bzrlib.smart import server
     ### We may need a little more test framework support to construct an
     ### appropriate RemoteTransport in the future.
-    return [(SmartTCPTransport, SmartTCPServer_for_testing)]
+    return [(SmartTCPTransport, server.SmartTCPServer_for_testing)]

=== modified file bzrlib/builtins.py // last-changed:andrew.bennetts at canonical.
... com-20070406011930-wy4emdgu3yu527pm
--- bzrlib/builtins.py
+++ bzrlib/builtins.py
@@ -3224,7 +3224,8 @@
         ]
 
     def run(self, port=None, inet=False, directory=None, allow_writes=False):
-        from bzrlib.transport import smart
+        from bzrlib.smart import server
+        from bzrlib.transport import remote
         from bzrlib.transport import get_transport
         if directory is None:
             directory = os.getcwd()
@@ -3233,10 +3234,10 @@
             url = 'readonly+' + url
         t = get_transport(url)
         if inet:
-            server = smart.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
+            smart_server = remote.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
         else:
             if port is None:
-                port = smart.BZR_DEFAULT_PORT
+                port = remote.BZR_DEFAULT_PORT
                 host = '127.0.0.1'
             else:
                 if ':' in port:
@@ -3244,10 +3245,10 @@
                 else:
                     host = '127.0.0.1'
                 port = int(port)
-            server = smart.SmartTCPServer(t, host=host, port=port)
-            print 'listening on port: ', server.port
+            smart_server = server.SmartTCPServer(t, host=host, port=port)
+            print 'listening on port: ', smart_server.port
             sys.stdout.flush()
-        server.serve()
+        smart_server.serve()
 
 class cmd_join(Command):
     """Combine a subtree into its containing tree.

=== modified file bzrlib/tests/HTTPTestUtil.py // last-changed:andrew.bennetts@
... canonical.com-20070409044955-h3ijql5cvqxia4d4
--- bzrlib/tests/HTTPTestUtil.py
+++ bzrlib/tests/HTTPTestUtil.py
@@ -28,8 +28,8 @@
     )
 from bzrlib.transport import (
     get_transport,
-    smart,
     )
+from bzrlib.smart import protocol
 
 
 class WallRequestHandler(TestingHTTPRequestHandler):
@@ -130,7 +130,7 @@
         # we have to stop early due to error, but we would also have to use the
         # HTTP trailer facility which may not be widely available.
         out_buffer = StringIO()
-        smart_protocol_request = smart.SmartServerRequestProtocolOne(
+        smart_protocol_request = protocol.SmartServerRequestProtocolOne(
                 transport, out_buffer.write)
         # if this fails, we should return 400 bad request, but failure is
         # failure for now - RBC 20060919

=== modified file bzrlib/tests/blackbox/test_serve.py // last-changed:andrew.be
... nnetts at canonical.com-20070405152057-gokz8syll1lk2nrm
--- bzrlib/tests/blackbox/test_serve.py
+++ bzrlib/tests/blackbox/test_serve.py
@@ -31,7 +31,7 @@
 from bzrlib.bzrdir import BzrDir
 from bzrlib.errors import ParamikoNotPresent
 from bzrlib.tests import TestCaseWithTransport, TestSkipped
-from bzrlib.transport import get_transport, smart
+from bzrlib.transport import get_transport, remote
 
 
 class TestBzrServe(TestCaseWithTransport):
@@ -68,9 +68,9 @@
         # Connect to the server
         # We use this url because while this is no valid URL to connect to this
         # server instance, the transport needs a URL.
-        medium = smart.SmartSimplePipesClientMedium(
+        medium = remote.SmartSimplePipesClientMedium(
             process.stdout, process.stdin)
-        transport = smart.SmartTransport('bzr://localhost/', medium=medium)
+        transport = remote.SmartTransport('bzr://localhost/', medium=medium)
         return process, transport
 
     def start_server_port(self, extra_options=()):

=== modified file bzrlib/tests/test_smart_transport.py // last-changed:andrew.b
... ennetts at canonical.com-20070410020914-rjhtq6bfcbrj2vjs
--- bzrlib/tests/test_smart_transport.py
+++ bzrlib/tests/test_smart_transport.py
@@ -30,6 +30,12 @@
         tests,
         urlutils,
         )
+from bzrlib.smart import (
+        medium,
+        protocol,
+        request,
+        server,
+)
 from bzrlib.tests.HTTPTestUtil import (
         HTTPServerWithSmarts,
         SmartRequestHandler,
@@ -38,7 +44,7 @@
         get_transport,
         local,
         memory,
-        smart,
+        remote,
         )
 from bzrlib.transport.http import SmartClientHTTPMediumRequest
 
@@ -85,8 +91,8 @@
         sock.bind(('127.0.0.1', 0))
         sock.listen(1)
         port = sock.getsockname()[1]
-        medium = smart.SmartTCPClientMedium('127.0.0.1', port)
-        return sock, medium
+        client_medium = medium.SmartTCPClientMedium('127.0.0.1', port)
+        return sock, client_medium
 
     def receive_bytes_on_server(self, sock, bytes):
         """Accept a connection on sock and read 3 bytes.
@@ -108,24 +114,24 @@
         # this just ensures that the constructor stays parameter-free which
         # is important for reuse : some subclasses will dynamically connect,
         # others are always on, etc.
-        medium = smart.SmartClientStreamMedium()
+        client_medium = medium.SmartClientStreamMedium()
 
     def test_construct_smart_client_medium(self):
         # the base client medium takes no parameters
-        medium = smart.SmartClientMedium()
+        client_medium = medium.SmartClientMedium()
     
     def test_construct_smart_simple_pipes_client_medium(self):
         # the SimplePipes client medium takes two pipes:
         # readable pipe, writeable pipe.
         # Constructing one should just save these and do nothing.
         # We test this by passing in None.
-        medium = smart.SmartSimplePipesClientMedium(None, None)
+        client_medium = medium.SmartSimplePipesClientMedium(None, None)
         
     def test_simple_pipes_client_request_type(self):
         # SimplePipesClient should use SmartClientStreamMediumRequest's.
-        medium = smart.SmartSimplePipesClientMedium(None, None)
-        request = medium.get_request()
-        self.assertIsInstance(request, smart.SmartClientStreamMediumRequest)
+        client_medium = medium.SmartSimplePipesClientMedium(None, None)
+        request = client_medium.get_request()
+        self.assertIsInstance(request, medium.SmartClientStreamMediumRequest)
 
     def test_simple_pipes_client_get_concurrent_requests(self):
         # the simple_pipes client does not support pipelined requests:
@@ -135,30 +141,30 @@
         # classes - as the sibling classes share this logic, they do not have
         # explicit tests for this.
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        request = medium.get_request()
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        request = client_medium.get_request()
         request.finished_writing()
         request.finished_reading()
-        request2 = medium.get_request()
+        request2 = client_medium.get_request()
         request2.finished_writing()
         request2.finished_reading()
 
     def test_simple_pipes_client__accept_bytes_writes_to_writable(self):
         # accept_bytes writes to the writeable pipe.
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        medium._accept_bytes('abc')
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        client_medium._accept_bytes('abc')
         self.assertEqual('abc', output.getvalue())
     
     def test_simple_pipes_client_disconnect_does_nothing(self):
         # calling disconnect does nothing.
         input = StringIO()
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
         # send some bytes to ensure disconnecting after activity still does not
         # close.
-        medium._accept_bytes('abc')
-        medium.disconnect()
+        client_medium._accept_bytes('abc')
+        client_medium.disconnect()
         self.assertFalse(input.closed)
         self.assertFalse(output.closed)
 
@@ -167,10 +173,10 @@
         # accept_bytes writes to.
         input = StringIO()
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        medium._accept_bytes('abc')
-        medium.disconnect()
-        medium._accept_bytes('abc')
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        client_medium._accept_bytes('abc')
+        client_medium.disconnect()
+        client_medium._accept_bytes('abc')
         self.assertFalse(input.closed)
         self.assertFalse(output.closed)
         self.assertEqual('abcabc', output.getvalue())
@@ -178,17 +184,17 @@
     def test_simple_pipes_client_ignores_disconnect_when_not_connected(self):
         # Doing a disconnect on a new (and thus unconnected) SimplePipes medium
         # does nothing.
-        medium = smart.SmartSimplePipesClientMedium(None, None)
-        medium.disconnect()
+        client_medium = medium.SmartSimplePipesClientMedium(None, None)
+        client_medium.disconnect()
 
     def test_simple_pipes_client_can_always_read(self):
         # SmartSimplePipesClientMedium is never disconnected, so read_bytes
         # always tries to read from the underlying pipe.
         input = StringIO('abcdef')
-        medium = smart.SmartSimplePipesClientMedium(input, None)
-        self.assertEqual('abc', medium.read_bytes(3))
-        medium.disconnect()
-        self.assertEqual('def', medium.read_bytes(3))
+        client_medium = medium.SmartSimplePipesClientMedium(input, None)
+        self.assertEqual('abc', client_medium.read_bytes(3))
+        client_medium.disconnect()
+        self.assertEqual('def', client_medium.read_bytes(3))
         
     def test_simple_pipes_client_supports__flush(self):
         # invoking _flush on a SimplePipesClient should flush the output 
@@ -200,12 +206,12 @@
         flush_calls = []
         def logging_flush(): flush_calls.append('flush')
         output.flush = logging_flush
-        medium = smart.SmartSimplePipesClientMedium(input, output)
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
         # this call is here to ensure we only flush once, not on every
         # _accept_bytes call.
-        medium._accept_bytes('abc')
-        medium._flush()
-        medium.disconnect()
+        client_medium._accept_bytes('abc')
+        client_medium._flush()
+        client_medium.disconnect()
         self.assertEqual(['flush'], flush_calls)
 
     def test_construct_smart_ssh_client_medium(self):
@@ -219,7 +225,7 @@
         unopened_port = sock.getsockname()[1]
         # having vendor be invalid means that if it tries to connect via the
         # vendor it will blow up.
-        medium = smart.SmartSSHClientMedium('127.0.0.1', unopened_port,
+        client_medium = medium.SmartSSHClientMedium('127.0.0.1', unopened_port,
             username=None, password=None, vendor="not a vendor")
         sock.close()
 
@@ -228,9 +234,9 @@
         # it bytes.
         output = StringIO()
         vendor = StringIOSSHVendor(StringIO(), output)
-        medium = smart.SmartSSHClientMedium('a hostname', 'a port', 'a username',
-            'a password', vendor)
-        medium._accept_bytes('abc')
+        client_medium = medium.SmartSSHClientMedium(
+            'a hostname', 'a port', 'a username', 'a password', vendor)
+        client_medium._accept_bytes('abc')
         self.assertEqual('abc', output.getvalue())
         self.assertEqual([('connect_ssh', 'a username', 'a password',
             'a hostname', 'a port',
@@ -247,9 +253,9 @@
             osutils.set_or_unset_env('BZR_REMOTE_PATH', orig_bzr_remote_path)
         self.addCleanup(cleanup_environ)
         os.environ['BZR_REMOTE_PATH'] = 'fugly'
-        medium = smart.SmartSSHClientMedium('a hostname', 'a port', 'a username',
+        client_medium = medium.SmartSSHClientMedium('a hostname', 'a port', 'a username',
             'a password', vendor)
-        medium._accept_bytes('abc')
+        client_medium._accept_bytes('abc')
         self.assertEqual('abc', output.getvalue())
         self.assertEqual([('connect_ssh', 'a username', 'a password',
             'a hostname', 'a port',
@@ -262,9 +268,9 @@
         input = StringIO()
         output = StringIO()
         vendor = StringIOSSHVendor(input, output)
-        medium = smart.SmartSSHClientMedium('a hostname', vendor=vendor)
-        medium._accept_bytes('abc')
-        medium.disconnect()
+        client_medium = medium.SmartSSHClientMedium('a hostname', vendor=vendor)
+        client_medium._accept_bytes('abc')
+        client_medium.disconnect()
         self.assertTrue(input.closed)
         self.assertTrue(output.closed)
         self.assertEqual([
@@ -282,17 +288,17 @@
         input = StringIO()
         output = StringIO()
         vendor = StringIOSSHVendor(input, output)
-        medium = smart.SmartSSHClientMedium('a hostname', vendor=vendor)
-        medium._accept_bytes('abc')
-        medium.disconnect()
+        client_medium = medium.SmartSSHClientMedium('a hostname', vendor=vendor)
+        client_medium._accept_bytes('abc')
+        client_medium.disconnect()
         # the disconnect has closed output, so we need a new output for the
         # new connection to write to.
         input2 = StringIO()
         output2 = StringIO()
         vendor.read_from = input2
         vendor.write_to = output2
-        medium._accept_bytes('abc')
-        medium.disconnect()
+        client_medium._accept_bytes('abc')
+        client_medium.disconnect()
         self.assertTrue(input.closed)
         self.assertTrue(output.closed)
         self.assertTrue(input2.closed)
@@ -310,15 +316,15 @@
     def test_ssh_client_ignores_disconnect_when_not_connected(self):
         # Doing a disconnect on a new (and thus unconnected) SSH medium
         # does not fail.  It's ok to disconnect an unconnected medium.
-        medium = smart.SmartSSHClientMedium(None)
-        medium.disconnect()
+        client_medium = medium.SmartSSHClientMedium(None)
+        client_medium.disconnect()
 
     def test_ssh_client_raises_on_read_when_not_connected(self):
         # Doing a read on a new (and thus unconnected) SSH medium raises
         # MediumNotConnected.
-        medium = smart.SmartSSHClientMedium(None)
-        self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 0)
-        self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 1)
+        client_medium = medium.SmartSSHClientMedium(None)
+        self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 0)
+        self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 1)
 
     def test_ssh_client_supports__flush(self):
         # invoking _flush on a SSHClientMedium should flush the output 
@@ -331,12 +337,12 @@
         def logging_flush(): flush_calls.append('flush')
         output.flush = logging_flush
         vendor = StringIOSSHVendor(input, output)
-        medium = smart.SmartSSHClientMedium('a hostname', vendor=vendor)
+        client_medium = medium.SmartSSHClientMedium('a hostname', vendor=vendor)
         # this call is here to ensure we only flush once, not on every
         # _accept_bytes call.
-        medium._accept_bytes('abc')
-        medium._flush()
-        medium.disconnect()
+        client_medium._accept_bytes('abc')
+        client_medium._flush()
+        client_medium.disconnect()
         self.assertEqual(['flush'], flush_calls)
         
     def test_construct_smart_tcp_client_medium(self):
@@ -345,7 +351,7 @@
         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         sock.bind(('127.0.0.1', 0))
         unopened_port = sock.getsockname()[1]
-        medium = smart.SmartTCPClientMedium('127.0.0.1', unopened_port)
+        client_medium = medium.SmartTCPClientMedium('127.0.0.1', unopened_port)
         sock.close()
 
     def test_tcp_client_connects_on_first_use(self):
@@ -378,15 +384,15 @@
     def test_tcp_client_ignores_disconnect_when_not_connected(self):
         # Doing a disconnect on a new (and thus unconnected) TCP medium
         # does not fail.  It's ok to disconnect an unconnected medium.
-        medium = smart.SmartTCPClientMedium(None, None)
-        medium.disconnect()
+        client_medium = medium.SmartTCPClientMedium(None, None)
+        client_medium.disconnect()
 
     def test_tcp_client_raises_on_read_when_not_connected(self):
         # Doing a read on a new (and thus unconnected) TCP medium raises
         # MediumNotConnected.
-        medium = smart.SmartTCPClientMedium(None, None)
-        self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 0)
-        self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 1)
+        client_medium = medium.SmartTCPClientMedium(None, None)
+        self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 0)
+        self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 1)
 
     def test_tcp_client_supports__flush(self):
         # invoking _flush on a TCPClientMedium should do something useful.
@@ -421,8 +427,8 @@
         # WritingCompleted to prevent bad assumptions on stream environments
         # breaking the needs of message-based environments.
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         request.finished_writing()
         self.assertRaises(errors.WritingCompleted, request.accept_bytes, None)
 
@@ -432,8 +438,8 @@
         # and checking that the pipes get the data.
         input = StringIO()
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         request.accept_bytes('123')
         request.finished_writing()
         request.finished_reading()
@@ -444,34 +450,34 @@
         # constructing a SmartClientStreamMediumRequest on a StreamMedium sets
         # the current request to the new SmartClientStreamMediumRequest
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        request = smart.SmartClientStreamMediumRequest(medium)
-        self.assertIs(medium._current_request, request)
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
+        self.assertIs(client_medium._current_request, request)
 
     def test_construct_while_another_request_active_throws(self):
         # constructing a SmartClientStreamMediumRequest on a StreamMedium with
         # a non-None _current_request raises TooManyConcurrentRequests.
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        medium._current_request = "a"
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        client_medium._current_request = "a"
         self.assertRaises(errors.TooManyConcurrentRequests,
-            smart.SmartClientStreamMediumRequest, medium)
+            medium.SmartClientStreamMediumRequest, client_medium)
 
     def test_finished_read_clears_current_request(self):
         # calling finished_reading clears the current request from the requests
         # medium
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         request.finished_writing()
         request.finished_reading()
-        self.assertEqual(None, medium._current_request)
+        self.assertEqual(None, client_medium._current_request)
 
     def test_finished_read_before_finished_write_errors(self):
         # calling finished_reading before calling finished_writing triggers a
         # WritingNotComplete error.
-        medium = smart.SmartSimplePipesClientMedium(None, None)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(None, None)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         self.assertRaises(errors.WritingNotComplete, request.finished_reading)
         
     def test_read_bytes(self):
@@ -483,8 +489,8 @@
         # smoke tests.
         input = StringIO('321')
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         request.finished_writing()
         self.assertEqual('321', request.read_bytes(3))
         request.finished_reading()
@@ -496,8 +502,8 @@
         # WritingNotComplete error because the Smart protocol is designed to be
         # compatible with strict message based protocols like HTTP where the
         # request cannot be submitted until the writing has completed.
-        medium = smart.SmartSimplePipesClientMedium(None, None)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(None, None)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         self.assertRaises(errors.WritingNotComplete, request.read_bytes, None)
 
     def test_read_bytes_after_finished_reading_errors(self):
@@ -505,8 +511,8 @@
         # ReadingCompleted to prevent bad assumptions on stream environments
         # breaking the needs of message-based environments.
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        request = smart.SmartClientStreamMediumRequest(medium)
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        request = medium.SmartClientStreamMediumRequest(client_medium)
         request.finished_writing()
         request.finished_reading()
         self.assertRaises(errors.ReadingCompleted, request.read_bytes, None)
@@ -520,20 +526,20 @@
         # the default or a parameterized class, but rather use the
         # TestCaseWithTransport infrastructure to set up a smart server and
         # transport.
-        self.transport_server = smart.SmartTCPServer_for_testing
+        self.transport_server = server.SmartTCPServer_for_testing
 
     def test_plausible_url(self):
         self.assert_(self.get_url().startswith('bzr://'))
 
     def test_probe_transport(self):
         t = self.get_transport()
-        self.assertIsInstance(t, smart.SmartTransport)
+        self.assertIsInstance(t, remote.SmartTransport)
 
     def test_get_medium_from_transport(self):
         """Remote transport has a medium always, which it can return."""
         t = self.get_transport()
-        medium = t.get_smart_medium()
-        self.assertIsInstance(medium, smart.SmartClientMedium)
+        smart_medium = t.get_smart_medium()
+        self.assertIsInstance(smart_medium, medium.SmartClientMedium)
 
 
 class ErrorRaisingProtocol(object):
@@ -588,11 +594,11 @@
         to_server = StringIO('hello\n')
         from_server = StringIO()
         transport = local.LocalTransport(urlutils.local_path_to_url('/'))
-        server = smart.SmartServerPipeStreamMedium(
+        server = medium.SmartServerPipeStreamMedium(
             to_server, from_server, transport)
-        protocol = smart.SmartServerRequestProtocolOne(transport,
+        smart_protocol = protocol.SmartServerRequestProtocolOne(transport,
                 from_server.write)
-        server._serve_one_request(protocol)
+        server._serve_one_request(smart_protocol)
         self.assertEqual('ok\0011\n',
                          from_server.getvalue())
 
@@ -601,11 +607,11 @@
         transport.put_bytes('testfile', 'contents\nof\nfile\n')
         to_server = StringIO('get\001./testfile\n')
         from_server = StringIO()
-        server = smart.SmartServerPipeStreamMedium(
+        server = medium.SmartServerPipeStreamMedium(
             to_server, from_server, transport)
-        protocol = smart.SmartServerRequestProtocolOne(transport,
+        smart_protocol = protocol.SmartServerRequestProtocolOne(transport,
                 from_server.write)
-        server._serve_one_request(protocol)
+        server._serve_one_request(smart_protocol)
         self.assertEqual('ok\n'
                          '17\n'
                          'contents\nof\nfile\n'
@@ -619,11 +625,11 @@
         transport.put_bytes(utf8_filename, 'contents\nof\nfile\n')
         to_server = StringIO('get\001' + utf8_filename + '\n')
         from_server = StringIO()
-        server = smart.SmartServerPipeStreamMedium(
+        server = medium.SmartServerPipeStreamMedium(
             to_server, from_server, transport)
-        protocol = smart.SmartServerRequestProtocolOne(transport,
+        smart_protocol = protocol.SmartServerRequestProtocolOne(transport,
                 from_server.write)
-        server._serve_one_request(protocol)
+        server._serve_one_request(smart_protocol)
         self.assertEqual('ok\n'
                          '17\n'
                          'contents\nof\nfile\n'
@@ -634,7 +640,8 @@
         sample_request_bytes = 'command\n9\nbulk datadone\n'
         to_server = StringIO(sample_request_bytes)
         from_server = StringIO()
-        server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
+        server = medium.SmartServerPipeStreamMedium(
+            to_server, from_server, None)
         sample_protocol = SampleRequest(expected_bytes=sample_request_bytes)
         server._serve_one_request(sample_protocol)
         self.assertEqual('', from_server.getvalue())
@@ -644,7 +651,7 @@
     def test_socket_stream_with_bulk_data(self):
         sample_request_bytes = 'command\n9\nbulk datadone\n'
         server_sock, client_sock = self.portable_socket_pair()
-        server = smart.SmartServerSocketStreamMedium(
+        server = medium.SmartServerSocketStreamMedium(
             server_sock, None)
         sample_protocol = SampleRequest(expected_bytes=sample_request_bytes)
         client_sock.sendall(sample_request_bytes)
@@ -657,14 +664,14 @@
     def test_pipe_like_stream_shutdown_detection(self):
         to_server = StringIO('')
         from_server = StringIO()
-        server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
+        server = medium.SmartServerPipeStreamMedium(to_server, from_server, None)
         server._serve_one_request(SampleRequest('x'))
         self.assertTrue(server.finished)
         
     def test_socket_stream_shutdown_detection(self):
         server_sock, client_sock = self.portable_socket_pair()
         client_sock.close()
-        server = smart.SmartServerSocketStreamMedium(
+        server = medium.SmartServerSocketStreamMedium(
             server_sock, None)
         server._serve_one_request(SampleRequest('x'))
         self.assertTrue(server.finished)
@@ -676,7 +683,8 @@
         sample_request_bytes = 'command\n'
         to_server = StringIO(sample_request_bytes * 2)
         from_server = StringIO()
-        server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
+        server = medium.SmartServerPipeStreamMedium(
+            to_server, from_server, None)
         first_protocol = SampleRequest(expected_bytes=sample_request_bytes)
         server._serve_one_request(first_protocol)
         self.assertEqual(0, first_protocol.next_read_size())
@@ -696,7 +704,7 @@
         # been received seperately.
         sample_request_bytes = 'command\n'
         server_sock, client_sock = self.portable_socket_pair()
-        server = smart.SmartServerSocketStreamMedium(
+        server = medium.SmartServerSocketStreamMedium(
             server_sock, None)
         first_protocol = SampleRequest(expected_bytes=sample_request_bytes)
         # Put two whole requests on the wire.
@@ -723,7 +731,8 @@
         def close():
             self.closed = True
         from_server.close = close
-        server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
+        server = medium.SmartServerPipeStreamMedium(
+            to_server, from_server, None)
         fake_protocol = ErrorRaisingProtocol(Exception('boom'))
         server._serve_one_request(fake_protocol)
         self.assertEqual('', from_server.getvalue())
@@ -735,7 +744,7 @@
         # not discard the contents.
         from StringIO import StringIO
         server_sock, client_sock = self.portable_socket_pair()
-        server = smart.SmartServerSocketStreamMedium(
+        server = medium.SmartServerSocketStreamMedium(
             server_sock, None)
         fake_protocol = ErrorRaisingProtocol(Exception('boom'))
         server._serve_one_request(fake_protocol)
@@ -749,7 +758,8 @@
         # not discard the contents.
         to_server = StringIO('')
         from_server = StringIO()
-        server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
+        server = medium.SmartServerPipeStreamMedium(
+            to_server, from_server, None)
         fake_protocol = ErrorRaisingProtocol(KeyboardInterrupt('boom'))
         self.assertRaises(
             KeyboardInterrupt, server._serve_one_request, fake_protocol)
@@ -757,7 +767,7 @@
 
     def test_socket_stream_keyboard_interrupt_handling(self):
         server_sock, client_sock = self.portable_socket_pair()
-        server = smart.SmartServerSocketStreamMedium(
+        server = medium.SmartServerSocketStreamMedium(
             server_sock, None)
         fake_protocol = ErrorRaisingProtocol(KeyboardInterrupt('boom'))
         self.assertRaises(
@@ -773,10 +783,10 @@
         class FlakyTransport(object):
             def get_bytes(self, path):
                 raise Exception("some random exception from inside server")
-        server = smart.SmartTCPServer(backing_transport=FlakyTransport())
-        server.start_background_thread()
+        smart_server = server.SmartTCPServer(backing_transport=FlakyTransport())
+        smart_server.start_background_thread()
         try:
-            transport = smart.SmartTCPTransport(server.get_url())
+            transport = remote.SmartTCPTransport(smart_server.get_url())
             try:
                 transport.get('something')
             except errors.TransportError, e:
@@ -784,7 +794,7 @@
             else:
                 self.fail("get did not raise expected error")
         finally:
-            server.stop_background_thread()
+            smart_server.stop_background_thread()
 
 
 class SmartTCPTests(tests.TestCase):
@@ -805,9 +815,9 @@
         if readonly:
             self.real_backing_transport = self.backing_transport
             self.backing_transport = get_transport("readonly+" + self.backing_transport.abspath('.'))
-        self.server = smart.SmartTCPServer(self.backing_transport)
+        self.server = server.SmartTCPServer(self.backing_transport)
         self.server.start_background_thread()
-        self.transport = smart.SmartTCPTransport(self.server.get_url())
+        self.transport = remote.SmartTCPTransport(self.server.get_url())
 
     def tearDown(self):
         if getattr(self, 'transport', None):
@@ -908,11 +918,11 @@
 
     def test_construct_request_handler(self):
         """Constructing a request handler should be easy and set defaults."""
-        handler = smart.SmartServerRequestHandler(None)
+        handler = request.SmartServerRequestHandler(None)
         self.assertFalse(handler.finished_reading)
 
     def test_hello(self):
-        handler = smart.SmartServerRequestHandler(None)
+        handler = request.SmartServerRequestHandler(None)
         handler.dispatch_command('hello', ())
         self.assertEqual(('ok', '1'), handler.response.args)
         self.assertEqual(None, handler.response.body)
@@ -924,14 +934,14 @@
         wt.add('hello')
         rev_id = wt.commit('add hello')
         
-        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler = request.SmartServerRequestHandler(self.get_transport())
         handler.dispatch_command('get_bundle', ('.', rev_id))
         bundle = serializer.read_bundle(StringIO(handler.response.body))
         self.assertEqual((), handler.response.args)
 
     def test_readonly_exception_becomes_transport_not_possible(self):
         """The response for a read-only error is ('ReadOnlyError')."""
-        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler = request.SmartServerRequestHandler(self.get_readonly_transport())
         # send a mkdir for foo, with no explicit mode - should fail.
         handler.dispatch_command('mkdir', ('foo', ''))
         # and the failure should be an explicit ReadOnlyError
@@ -943,14 +953,14 @@
 
     def test_hello_has_finished_body_on_dispatch(self):
         """The 'hello' command should set finished_reading."""
-        handler = smart.SmartServerRequestHandler(None)
+        handler = request.SmartServerRequestHandler(None)
         handler.dispatch_command('hello', ())
         self.assertTrue(handler.finished_reading)
         self.assertNotEqual(None, handler.response)
 
     def test_put_bytes_non_atomic(self):
         """'put_...' should set finished_reading after reading the bytes."""
-        handler = smart.SmartServerRequestHandler(self.get_transport())
+        handler = request.SmartServerRequestHandler(self.get_transport())
         handler.dispatch_command('put_non_atomic', ('a-file', '', 'F', ''))
         self.assertFalse(handler.finished_reading)
         handler.accept_body('1234')
@@ -964,7 +974,7 @@
     def test_readv_accept_body(self):
         """'readv' should set finished_reading after reading offsets."""
         self.build_tree(['a-file'])
-        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler = request.SmartServerRequestHandler(self.get_readonly_transport())
         handler.dispatch_command('readv', ('a-file', ))
         self.assertFalse(handler.finished_reading)
         handler.accept_body('2,')
@@ -979,7 +989,7 @@
     def test_readv_short_read_response_contents(self):
         """'readv' when a short read occurs sets the response appropriately."""
         self.build_tree(['a-file'])
-        handler = smart.SmartServerRequestHandler(self.get_readonly_transport())
+        handler = request.SmartServerRequestHandler(self.get_readonly_transport())
         handler.dispatch_command('readv', ('a-file', ))
         # read beyond the end of the file.
         handler.accept_body('100,1')
@@ -990,22 +1000,23 @@
         self.assertEqual(None, handler.response.body)
 
 
-class SmartTransportRegistration(tests.TestCase):
+class RemoteTransportRegistration(tests.TestCase):
 
     def test_registration(self):
         t = get_transport('bzr+ssh://example.com/path')
-        self.assertIsInstance(t, smart.SmartSSHTransport)
+        self.assertIsInstance(t, remote.SmartSSHTransport)
         self.assertEqual('example.com', t._host)
 
 
-class TestSmartTransport(tests.TestCase):
+class TestRemoteTransport(tests.TestCase):
         
     def test_use_connection_factory(self):
-        # We want to be able to pass a client as a parameter to SmartTransport.
+        # We want to be able to pass a client as a parameter to RemoteTransport.
         input = StringIO("ok\n3\nbardone\n")
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        transport = smart.SmartTransport('bzr://localhost/', medium=medium)
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        transport = remote.SmartTransport(
+            'bzr://localhost/', medium=client_medium)
 
         # We want to make sure the client is used when the first remote
         # method is called.  No data should have been sent, or read.
@@ -1023,17 +1034,18 @@
 
     def test__translate_error_readonly(self):
         """Sending a ReadOnlyError to _translate_error raises TransportNotPossible."""
-        medium = smart.SmartClientMedium()
-        transport = smart.SmartTransport('bzr://localhost/', medium=medium)
+        client_medium = medium.SmartClientMedium()
+        transport = remote.SmartTransport(
+            'bzr://localhost/', medium=client_medium)
         self.assertRaises(errors.TransportNotPossible,
             transport._translate_error, ("ReadOnlyError", ))
 
 
-class InstrumentedServerProtocol(smart.SmartServerStreamMedium):
+class InstrumentedServerProtocol(medium.SmartServerStreamMedium):
     """A smart server which is backed by memory and saves its write requests."""
 
     def __init__(self, write_output_list):
-        smart.SmartServerStreamMedium.__init__(self, memory.MemoryTransport())
+        medium.SmartServerStreamMedium.__init__(self, memory.MemoryTransport())
         self._write_output_list = write_output_list
 
 
@@ -1052,15 +1064,17 @@
 
     def setUp(self):
         super(TestSmartProtocol, self).setUp()
+        # XXX: self.server_to_client doesn't seem to be used.  If so,
+        # InstrumentedServerProtocol is redundant too.
         self.server_to_client = []
         self.to_server = StringIO()
         self.to_client = StringIO()
-        self.client_medium = smart.SmartSimplePipesClientMedium(self.to_client,
+        self.client_medium = medium.SmartSimplePipesClientMedium(self.to_client,
             self.to_server)
-        self.client_protocol = smart.SmartClientRequestProtocolOne(
+        self.client_protocol = protocol.SmartClientRequestProtocolOne(
             self.client_medium)
         self.smart_server = InstrumentedServerProtocol(self.server_to_client)
-        self.smart_server_request = smart.SmartServerRequestHandler(None)
+        self.smart_server_request = request.SmartServerRequestHandler(None)
 
     def assertOffsetSerialisation(self, expected_offsets, expected_serialised,
         client, smart_server_request):
@@ -1083,34 +1097,34 @@
 
     def build_protocol_waiting_for_body(self):
         out_stream = StringIO()
-        protocol = smart.SmartServerRequestProtocolOne(None, out_stream.write)
-        protocol.has_dispatched = True
-        protocol.request = smart.SmartServerRequestHandler(None)
+        smart_protocol = protocol.SmartServerRequestProtocolOne(None, out_stream.write)
+        smart_protocol.has_dispatched = True
+        smart_protocol.request = request.SmartServerRequestHandler(None)
         def handle_end_of_bytes():
             self.end_received = True
-            self.assertEqual('abcdefg', protocol.request._body_bytes)
-            protocol.request.response = smart.SmartServerResponse(('ok', ))
-        protocol.request._end_of_body_handler = handle_end_of_bytes
+            self.assertEqual('abcdefg', smart_protocol.request._body_bytes)
+            smart_protocol.request.response = request.SmartServerResponse(('ok', ))
+        smart_protocol.request._end_of_body_handler = handle_end_of_bytes
         # Call accept_bytes to make sure that internal state like _body_decoder
         # is initialised.  This test should probably be given a clearer
         # interface to work with that will not cause this inconsistency.
         #   -- Andrew Bennetts, 2006-09-28
-        protocol.accept_bytes('')
-        return protocol
+        smart_protocol.accept_bytes('')
+        return smart_protocol
 
     def test_construct_version_one_server_protocol(self):
-        protocol = smart.SmartServerRequestProtocolOne(None, None)
-        self.assertEqual('', protocol.excess_buffer)
-        self.assertEqual('', protocol.in_buffer)
-        self.assertFalse(protocol.has_dispatched)
-        self.assertEqual(1, protocol.next_read_size())
+        smart_protocol = protocol.SmartServerRequestProtocolOne(None, None)
+        self.assertEqual('', smart_protocol.excess_buffer)
+        self.assertEqual('', smart_protocol.in_buffer)
+        self.assertFalse(smart_protocol.has_dispatched)
+        self.assertEqual(1, smart_protocol.next_read_size())
 
     def test_construct_version_one_client_protocol(self):
         # we can construct a client protocol from a client medium request
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(None, output)
-        request = medium.get_request()
-        client_protocol = smart.SmartClientRequestProtocolOne(request)
+        client_medium = medium.SmartSimplePipesClientMedium(None, output)
+        request = client_medium.get_request()
+        client_protocol = protocol.SmartClientRequestProtocolOne(request)
 
     def test_server_offset_serialisation(self):
         """The Smart protocol serialises offsets as a comma and \n string.
@@ -1130,14 +1144,16 @@
 
     def test_accept_bytes_of_bad_request_to_protocol(self):
         out_stream = StringIO()
-        protocol = smart.SmartServerRequestProtocolOne(None, out_stream.write)
-        protocol.accept_bytes('abc')
-        self.assertEqual('abc', protocol.in_buffer)
-        protocol.accept_bytes('\n')
-        self.assertEqual("error\x01Generic bzr smart protocol error: bad request"
-            " 'abc'\n", out_stream.getvalue())
-        self.assertTrue(protocol.has_dispatched)
-        self.assertEqual(0, protocol.next_read_size())
+        smart_protocol = protocol.SmartServerRequestProtocolOne(
+            None, out_stream.write)
+        smart_protocol.accept_bytes('abc')
+        self.assertEqual('abc', smart_protocol.in_buffer)
+        smart_protocol.accept_bytes('\n')
+        self.assertEqual(
+            "error\x01Generic bzr smart protocol error: bad request 'abc'\n",
+            out_stream.getvalue())
+        self.assertTrue(smart_protocol.has_dispatched)
+        self.assertEqual(0, smart_protocol.next_read_size())
 
     def test_accept_body_bytes_to_protocol(self):
         protocol = self.build_protocol_waiting_for_body()
@@ -1150,24 +1166,26 @@
         self.assertTrue(self.end_received)
 
     def test_accept_request_and_body_all_at_once(self):
+        self._captureVar('NO_SMART_VFS', None)
         mem_transport = memory.MemoryTransport()
         mem_transport.put_bytes('foo', 'abcdefghij')
         out_stream = StringIO()
-        protocol = smart.SmartServerRequestProtocolOne(mem_transport,
+        smart_protocol = protocol.SmartServerRequestProtocolOne(mem_transport,
                 out_stream.write)
-        protocol.accept_bytes('readv\x01foo\n3\n3,3done\n')
-        self.assertEqual(0, protocol.next_read_size())
+        smart_protocol.accept_bytes('readv\x01foo\n3\n3,3done\n')
+        self.assertEqual(0, smart_protocol.next_read_size())
         self.assertEqual('readv\n3\ndefdone\n', out_stream.getvalue())
-        self.assertEqual('', protocol.excess_buffer)
-        self.assertEqual('', protocol.in_buffer)
+        self.assertEqual('', smart_protocol.excess_buffer)
+        self.assertEqual('', smart_protocol.in_buffer)
 
     def test_accept_excess_bytes_are_preserved(self):
         out_stream = StringIO()
-        protocol = smart.SmartServerRequestProtocolOne(None, out_stream.write)
-        protocol.accept_bytes('hello\nhello\n')
+        smart_protocol = protocol.SmartServerRequestProtocolOne(
+            None, out_stream.write)
+        smart_protocol.accept_bytes('hello\nhello\n')
         self.assertEqual("ok\x011\n", out_stream.getvalue())
-        self.assertEqual("hello\n", protocol.excess_buffer)
-        self.assertEqual("", protocol.in_buffer)
+        self.assertEqual("hello\n", smart_protocol.excess_buffer)
+        self.assertEqual("", smart_protocol.in_buffer)
 
     def test_accept_excess_bytes_after_body(self):
         protocol = self.build_protocol_waiting_for_body()
@@ -1181,20 +1199,22 @@
 
     def test_accept_excess_bytes_after_dispatch(self):
         out_stream = StringIO()
-        protocol = smart.SmartServerRequestProtocolOne(None, out_stream.write)
-        protocol.accept_bytes('hello\n')
+        smart_protocol = protocol.SmartServerRequestProtocolOne(
+            None, out_stream.write)
+        smart_protocol.accept_bytes('hello\n')
         self.assertEqual("ok\x011\n", out_stream.getvalue())
-        protocol.accept_bytes('hel')
-        self.assertEqual("hel", protocol.excess_buffer)
-        protocol.accept_bytes('lo\n')
-        self.assertEqual("hello\n", protocol.excess_buffer)
-        self.assertEqual("", protocol.in_buffer)
+        smart_protocol.accept_bytes('hel')
+        self.assertEqual("hel", smart_protocol.excess_buffer)
+        smart_protocol.accept_bytes('lo\n')
+        self.assertEqual("hello\n", smart_protocol.excess_buffer)
+        self.assertEqual("", smart_protocol.in_buffer)
 
     def test__send_response_sets_finished_reading(self):
-        protocol = smart.SmartServerRequestProtocolOne(None, lambda x: None)
-        self.assertEqual(1, protocol.next_read_size())
-        protocol._send_response(('x',))
-        self.assertEqual(0, protocol.next_read_size())
+        smart_protocol = protocol.SmartServerRequestProtocolOne(
+            None, lambda x: None)
+        self.assertEqual(1, smart_protocol.next_read_size())
+        smart_protocol._send_response(('x',))
+        self.assertEqual(0, smart_protocol.next_read_size())
 
     def test_query_version(self):
         """query_version on a SmartClientProtocolOne should return a number.
@@ -1208,9 +1228,10 @@
         # the error if the response is a non-understood version.
         input = StringIO('ok\x011\n')
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        self.assertEqual(1, protocol.query_version())
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        self.assertEqual(1, smart_protocol.query_version())
 
     def assertServerToClientEncoding(self, expected_bytes, expected_tuple,
             input_tuples):
@@ -1221,17 +1242,18 @@
         # expected bytes
         for input_tuple in input_tuples:
             server_output = StringIO()
-            server_protocol = smart.SmartServerRequestProtocolOne(
+            server_protocol = protocol.SmartServerRequestProtocolOne(
                 None, server_output.write)
             server_protocol._send_response(input_tuple)
             self.assertEqual(expected_bytes, server_output.getvalue())
-        # check the decoding of the client protocol from expected_bytes:
+        # check the decoding of the client smart_protocol from expected_bytes:
         input = StringIO(expected_bytes)
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        protocol.call('foo')
-        self.assertEqual(expected_tuple, protocol.read_response_tuple())
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol.call('foo')
+        self.assertEqual(expected_tuple, smart_protocol.read_response_tuple())
 
     def test_client_call_empty_response(self):
         # protocol.call() can get back an empty tuple as a response. This occurs
@@ -1246,14 +1268,15 @@
             [('a', 'b', '34')])
 
     def test_client_call_with_body_bytes_uploads(self):
-        # protocol.call_with_upload should length-prefix the bytes onto the 
+        # protocol.call_with_body_bytes should length-prefix the bytes onto the
         # wire.
         expected_bytes = "foo\n7\nabcdefgdone\n"
         input = StringIO("\n")
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        protocol.call_with_body_bytes(('foo', ), "abcdefg")
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol.call_with_body_bytes(('foo', ), "abcdefg")
         self.assertEqual(expected_bytes, output.getvalue())
 
     def test_client_call_with_body_readv_array(self):
@@ -1262,9 +1285,10 @@
         expected_bytes = "foo\n7\n1,2\n5,6done\n"
         input = StringIO("\n")
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        protocol.call_with_body_readv_array(('foo', ), [(1,2),(5,6)])
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol.call_with_body_readv_array(('foo', ), [(1,2),(5,6)])
         self.assertEqual(expected_bytes, output.getvalue())
 
     def test_client_read_body_bytes_all(self):
@@ -1274,11 +1298,12 @@
         server_bytes = "ok\n7\n1234567done\n"
         input = StringIO(server_bytes)
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        protocol.call('foo')
-        protocol.read_response_tuple(True)
-        self.assertEqual(expected_bytes, protocol.read_body_bytes())
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol.call('foo')
+        smart_protocol.read_response_tuple(True)
+        self.assertEqual(expected_bytes, smart_protocol.read_body_bytes())
 
     def test_client_read_body_bytes_incremental(self):
         # test reading a few bytes at a time from the body
@@ -1290,14 +1315,15 @@
         server_bytes = "ok\n7\n1234567done\n"
         input = StringIO(server_bytes)
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        protocol.call('foo')
-        protocol.read_response_tuple(True)
-        self.assertEqual(expected_bytes[0:2], protocol.read_body_bytes(2))
-        self.assertEqual(expected_bytes[2:4], protocol.read_body_bytes(2))
-        self.assertEqual(expected_bytes[4:6], protocol.read_body_bytes(2))
-        self.assertEqual(expected_bytes[6], protocol.read_body_bytes())
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol.call('foo')
+        smart_protocol.read_response_tuple(True)
+        self.assertEqual(expected_bytes[0:2], smart_protocol.read_body_bytes(2))
+        self.assertEqual(expected_bytes[2:4], smart_protocol.read_body_bytes(2))
+        self.assertEqual(expected_bytes[4:6], smart_protocol.read_body_bytes(2))
+        self.assertEqual(expected_bytes[6], smart_protocol.read_body_bytes())
 
     def test_client_cancel_read_body_does_not_eat_body_bytes(self):
         # cancelling the expected body needs to finish the request, but not
@@ -1306,13 +1332,15 @@
         server_bytes = "ok\n7\n1234567done\n"
         input = StringIO(server_bytes)
         output = StringIO()
-        medium = smart.SmartSimplePipesClientMedium(input, output)
-        protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
-        protocol.call('foo')
-        protocol.read_response_tuple(True)
-        protocol.cancel_read_body()
+        client_medium = medium.SmartSimplePipesClientMedium(input, output)
+        request = client_medium.get_request()
+        smart_protocol = protocol.SmartClientRequestProtocolOne(request)
+        smart_protocol.call('foo')
+        smart_protocol.read_response_tuple(True)
+        smart_protocol.cancel_read_body()
         self.assertEqual(3, input.tell())
-        self.assertRaises(errors.ReadingCompleted, protocol.read_body_bytes)
+        self.assertRaises(
+            errors.ReadingCompleted, smart_protocol.read_body_bytes)
 
 
 class LengthPrefixedBodyDecoder(tests.TestCase):
@@ -1321,14 +1349,14 @@
     # something similar to the ProtocolBase method.
 
     def test_construct(self):
-        decoder = smart.LengthPrefixedBodyDecoder()
+        decoder = protocol.LengthPrefixedBodyDecoder()
         self.assertFalse(decoder.finished_reading)
         self.assertEqual(6, decoder.next_read_size())
         self.assertEqual('', decoder.read_pending_data())
         self.assertEqual('', decoder.unused_data)
 
     def test_accept_bytes(self):
-        decoder = smart.LengthPrefixedBodyDecoder()
+        decoder = protocol.LengthPrefixedBodyDecoder()
         decoder.accept_bytes('')
         self.assertFalse(decoder.finished_reading)
         self.assertEqual(6, decoder.next_read_size())
@@ -1361,7 +1389,7 @@
         self.assertEqual('blarg', decoder.unused_data)
         
     def test_accept_bytes_all_at_once_with_excess(self):
-        decoder = smart.LengthPrefixedBodyDecoder()
+        decoder = protocol.LengthPrefixedBodyDecoder()
         decoder.accept_bytes('1\nadone\nunused')
         self.assertTrue(decoder.finished_reading)
         self.assertEqual(1, decoder.next_read_size())
@@ -1369,7 +1397,7 @@
         self.assertEqual('unused', decoder.unused_data)
 
     def test_accept_bytes_exact_end_of_body(self):
-        decoder = smart.LengthPrefixedBodyDecoder()
+        decoder = protocol.LengthPrefixedBodyDecoder()
         decoder.accept_bytes('1\na')
         self.assertFalse(decoder.finished_reading)
         self.assertEqual(5, decoder.next_read_size())
@@ -1393,21 +1421,22 @@
 
 class HTTPTunnellingSmokeTest(tests.TestCaseWithTransport):
     
+    def setUp(self):
+        super(HTTPTunnellingSmokeTest, self).setUp()
+        # We use the VFS layer as part of HTTP tunnelling tests.
+        self._captureVar('NO_SMART_VFS', None)
+
     def _test_bulk_data(self, url_protocol):
         # We should be able to send and receive bulk data in a single message.
         # The 'readv' command in the smart protocol both sends and receives bulk
         # data, so we use that.
         self.build_tree(['data-file'])
-        http_server = HTTPServerWithSmarts()
-        http_server._url_protocol = url_protocol
-        http_server.setUp()
-        self.addCleanup(http_server.tearDown)
-
-        http_transport = get_transport(http_server.get_url())
-
+        self.transport_readonly_server = HTTPServerWithSmarts
+
+        http_transport = self.get_readonly_transport()
         medium = http_transport.get_smart_medium()
         #remote_transport = RemoteTransport('fake_url', medium)
-        remote_transport = smart.SmartTransport('/', medium=medium)
+        remote_transport = remote.SmartTransport('/', medium=medium)
         self.assertEqual(
             [(0, "c")], list(remote_transport.readv("data-file", [(0,1)])))
 
@@ -1432,7 +1461,7 @@
     def _test_http_send_smart_request(self, url_protocol):
         http_server = HTTPServerWithSmarts()
         http_server._url_protocol = url_protocol
-        http_server.setUp()
+        http_server.setUp(self.get_vfs_only_server())
         self.addCleanup(http_server.tearDown)
 
         post_body = 'hello\n'
@@ -1454,23 +1483,19 @@
         self._test_http_send_smart_request('http+urllib')
 
     def test_http_server_with_smarts(self):
-        http_server = HTTPServerWithSmarts()
-        http_server.setUp()
-        self.addCleanup(http_server.tearDown)
+        self.transport_readonly_server = HTTPServerWithSmarts
 
         post_body = 'hello\n'
         expected_reply_body = 'ok\x011\n'
 
-        smart_server_url = http_server.get_url() + '.bzr/smart'
+        smart_server_url = self.get_readonly_url('.bzr/smart')
         reply = urllib2.urlopen(smart_server_url, post_body).read()
 
         self.assertEqual(expected_reply_body, reply)
 
     def test_smart_http_server_post_request_handler(self):
-        http_server = HTTPServerWithSmarts()
-        http_server.setUp()
-        self.addCleanup(http_server.tearDown)
-        httpd = http_server._get_httpd()
+        self.transport_readonly_server = HTTPServerWithSmarts
+        httpd = self.get_readonly_server()._get_httpd()
 
         socket = SampleSocket(
             'POST /.bzr/smart HTTP/1.0\r\n'
@@ -1512,7 +1537,7 @@
         else:
             return self.writefile
 
-        
+
 # TODO: Client feature that does get_bundle and then installs that into a
 # branch; this can be used in place of the regular pull/fetch operation when
 # coming from a smart server.

=== modified file bzrlib/tests/test_transport_implementations.py // last-change
... d:andrew.bennetts at canonical.com-20070409044955-h3ijql5cvqxia4d4
--- bzrlib/tests/test_transport_implementations.py
+++ bzrlib/tests/test_transport_implementations.py
@@ -38,7 +38,8 @@
 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.smart import medium
+from bzrlib.transport import memory, remote
 import bzrlib.transport
 
 
@@ -1306,7 +1307,7 @@
         transport = self.get_transport()
         try:
             client_medium = transport.get_smart_medium()
-            self.assertIsInstance(client_medium, smart.SmartClientMedium)
+            self.assertIsInstance(client_medium, medium.SmartClientMedium)
         except errors.NoSmartMedium:
             # as long as we got it we're fine
             pass

=== modified file bzrlib/transport/__init__.py // last-changed:andrew.bennetts@
... canonical.com-20070405152057-gokz8syll1lk2nrm
--- bzrlib/transport/__init__.py
+++ bzrlib/transport/__init__.py
@@ -1251,11 +1251,11 @@
                         'bzrlib.transport.fakevfat',
                         'FakeVFATTransportDecorator')
 register_lazy_transport('bzr://',
-                        'bzrlib.transport.smart',
+                        'bzrlib.transport.remote',
                         'SmartTCPTransport')
 register_lazy_transport('bzr+http://',
-                        'bzrlib.transport.smart',
+                        'bzrlib.transport.remote',
                         'SmartHTTPTransport')
 register_lazy_transport('bzr+ssh://',
-                        'bzrlib.transport.smart',
+                        'bzrlib.transport.remote',
                         'SmartSSHTransport')

=== modified file bzrlib/transport/http/__init__.py // last-changed:andrew.benn
... etts at canonical.com-20070409044955-h3ijql5cvqxia4d4
--- bzrlib/transport/http/__init__.py
+++ bzrlib/transport/http/__init__.py
@@ -27,9 +27,9 @@
 import sys
 
 from bzrlib import errors, ui
+from bzrlib.smart import medium
 from bzrlib.trace import mutter
 from bzrlib.transport import (
-    smart,
     Transport,
     )
 
@@ -113,7 +113,7 @@
     return m
 
 
-class HttpTransportBase(Transport, smart.SmartClientMedium):
+class HttpTransportBase(Transport, medium.SmartClientMedium):
     """Base class for http implementations.
 
     Does URL parsing, etc, but not any network IO.
@@ -505,11 +505,11 @@
         return body_filelike
 
 
-class SmartClientHTTPMediumRequest(smart.SmartClientMediumRequest):
+class SmartClientHTTPMediumRequest(medium.SmartClientMediumRequest):
     """A SmartClientMediumRequest that works with an HTTP medium."""
 
-    def __init__(self, medium):
-        smart.SmartClientMediumRequest.__init__(self, medium)
+    def __init__(self, smart_medium):
+        medium.SmartClientMediumRequest.__init__(self, smart_medium)
         self._buffer = ''
 
     def _accept_bytes(self, bytes):

=== modified file bzrlib/transport/http/wsgi.py // last-changed:andrew.bennetts
... @canonical.com-20070405152057-gokz8syll1lk2nrm
--- bzrlib/transport/http/wsgi.py
+++ bzrlib/transport/http/wsgi.py
@@ -22,7 +22,7 @@
 
 from cStringIO import StringIO
 
-from bzrlib.transport import chroot, get_transport, smart
+from bzrlib.transport import chroot, get_transport, remote
 from bzrlib.urlutils import local_path_to_url
     
 

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200704100
... 23142-7xgeph6572ikrnu8
# revision id: andrew.bennetts at canonical.com-20070410023142-7xgeph6572ikrnu8
# sha1: cbd992c8d69d993295b2e25bb8b42851a34a9aff
# inventory sha1: 15a2a88721ac0cd8b157cfee402a1762ccd7a0af
# parent ids:
#   andrew.bennetts at canonical.com-20070410022255-e1dhysj2zhukca5c
# base id: pqm at pqm.ubuntu.com-20070404213903-fe78a7a55c37ee95
# properties:
#   branch-nick: split-smart-part-1-rename

# message:
#   Add some missing docstrings and copyright boilerplate.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Tue 2007-04-10 12:22:55.773000002 +1000

=== modified file bzrlib/smart/protocol.py // encoding:base64
LS0tIGJ6cmxpYi9zbWFydC9wcm90b2NvbC5weQorKysgYnpybGliL3NtYXJ0L3Byb3RvY29sLnB5
CkBAIC0xLDMgKzEsMjIgQEAKKyMgQ29weXJpZ2h0IChDKSAyMDA2LCAyMDA3IENhbm9uaWNhbCBM
dGQKKyMKKyMgVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli
dXRlIGl0IGFuZC9vciBtb2RpZnkKKyMgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2Vu
ZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkKKyMgdGhlIEZyZWUgU29mdHdhcmUg
Rm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKKyMgKGF0IHlv
dXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KKyMKKyMgVGhpcyBwcm9ncmFtIGlzIGRpc3Ry
aWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCisjIGJ1dCBXSVRIT1VU
IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisjIE1F
UkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0
aGUKKyMgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KKyMKKyMg
WW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGlj
IExpY2Vuc2UKKyMgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhl
IEZyZWUgU29mdHdhcmUKKyMgRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0
ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQorCisiIiJXaXJlLWxldmVsIGVuY29k
aW5nIGFuZCBkZWNvZGluZyBvZiByZXF1ZXN0cyBhbmQgcmVzcG9uc2VzIGZvciB0aGUgc21hcnQK
K2NsaWVudCBhbmQgc2VydmVyLgorIiIiCiAKIAogZnJvbSBjU3RyaW5nSU8gaW1wb3J0IFN0cmlu
Z0lPCgo=

=== modified file bzrlib/smart/request.py // encoding:base64
LS0tIGJ6cmxpYi9zbWFydC9yZXF1ZXN0LnB5CisrKyBienJsaWIvc21hcnQvcmVxdWVzdC5weQpA
QCAtMSwzICsxLDIxIEBACisjIENvcHlyaWdodCAoQykgMjAwNiwgMjAwNyBDYW5vbmljYWwgTHRk
CisjCisjIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0
ZSBpdCBhbmQvb3IgbW9kaWZ5CisjIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVy
YWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5CisjIHRoZSBGcmVlIFNvZnR3YXJlIEZv
dW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCisjIChhdCB5b3Vy
IG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uCisjCisjIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmli
dXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAorIyBidXQgV0lUSE9VVCBB
TlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgorIyBNRVJD
SEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhl
CisjIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCisjCisjIFlv
dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM
aWNlbnNlCisjIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBG
cmVlIFNvZnR3YXJlCisjIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUg
MzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKKworIiIiQmFzaWMgc2VydmVyLXNpZGUg
bG9naWMgZm9yIGRlYWxpbmcgd2l0aCByZXF1ZXN0cy4iIiIKKwogCiBpbXBvcnQgdGVtcGZpbGUK
IAoK

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200704100
... 22255-e1dhysj2zhukca5c
# revision id: andrew.bennetts at canonical.com-20070410022255-e1dhysj2zhukca5c
# sha1: fa65f777e894cdbda8d98124a7870e820662f8af
# inventory sha1: 581bc475e1902c33fd2521bc8eef71e5afb94463
# parent ids:
#   andrew.bennetts at canonical.com-20070410020914-rjhtq6bfcbrj2vjs
# properties:
#   branch-nick: split-smart-part-1-rename

# message:
#   Tidy up accidental changes.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Tue 2007-04-10 12:09:14.796000004 +1000

=== modified file bzrlib/tests/test_smart_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NtYXJ0X3RyYW5zcG9ydC5weQorKysgYnpybGliL3Rlc3Rz
L3Rlc3Rfc21hcnRfdHJhbnNwb3J0LnB5CkBAIC0xMDc1LDggKzEwNzUsNiBAQAogICAgICAgICAg
ICAgc2VsZi5jbGllbnRfbWVkaXVtKQogICAgICAgICBzZWxmLnNtYXJ0X3NlcnZlciA9IEluc3Ry
dW1lbnRlZFNlcnZlclByb3RvY29sKHNlbGYuc2VydmVyX3RvX2NsaWVudCkKICAgICAgICAgc2Vs
Zi5zbWFydF9zZXJ2ZXJfcmVxdWVzdCA9IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxl
cihOb25lKQotIyAgICAgICAgc2VsZi5zbWFydF9zZXJ2ZXJfcmVxdWVzdCA9IHJlcXVlc3QuU21h
cnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcigKLSMgICAgICAgICAgICBOb25lLCByZXF1ZXN0LnJlcXVl
c3RfaGFuZGxlcnMpCiAKICAgICBkZWYgYXNzZXJ0T2Zmc2V0U2VyaWFsaXNhdGlvbihzZWxmLCBl
eHBlY3RlZF9vZmZzZXRzLCBleHBlY3RlZF9zZXJpYWxpc2VkLAogICAgICAgICBjbGllbnQsIHNt
YXJ0X3NlcnZlcl9yZXF1ZXN0KToKQEAgLTEwOTgsMjEgKzEwOTYsMjEgQEAKICAgICAgICAgc2Vs
Zi5hc3NlcnRFcXVhbChleHBlY3RlZF9zZXJpYWxpc2VkLCBzZXJpYWxpc2VkKQogCiAgICAgZGVm
IGJ1aWxkX3Byb3RvY29sX3dhaXRpbmdfZm9yX2JvZHkoc2VsZik6Ci0gICAgICAgb3V0X3N0cmVh
bSA9IFN0cmluZ0lPKCkKLSAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3RvY29sLlNtYXJ0U2Vy
dmVyUmVxdWVzdFByb3RvY29sT25lKE5vbmUsIG91dF9zdHJlYW0ud3JpdGUpCi0gICAgICAgc21h
cnRfcHJvdG9jb2wuaGFzX2Rpc3BhdGNoZWQgPSBUcnVlCi0gICAgICAgc21hcnRfcHJvdG9jb2wu
cmVxdWVzdCA9IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihOb25lKQotICAgICAg
IGRlZiBoYW5kbGVfZW5kX29mX2J5dGVzKCk6Ci0gICAgICAgICAgIHNlbGYuZW5kX3JlY2VpdmVk
ID0gVHJ1ZQotICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdhYmNkZWZnJywgc21hcnRfcHJv
dG9jb2wucmVxdWVzdC5fYm9keV9ieXRlcykKLSAgICAgICAgICAgc21hcnRfcHJvdG9jb2wucmVx
dWVzdC5yZXNwb25zZSA9IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ29rJywgKSkKLSAg
ICAgICBzbWFydF9wcm90b2NvbC5yZXF1ZXN0Ll9lbmRfb2ZfYm9keV9oYW5kbGVyID0gaGFuZGxl
X2VuZF9vZl9ieXRlcwotICAgICAgICMgQ2FsbCBhY2NlcHRfYnl0ZXMgdG8gbWFrZSBzdXJlIHRo
YXQgaW50ZXJuYWwgc3RhdGUgbGlrZSBfYm9keV9kZWNvZGVyCi0gICAgICAgIyBpcyBpbml0aWFs
aXNlZC4gIFRoaXMgdGVzdCBzaG91bGQgcHJvYmFibHkgYmUgZ2l2ZW4gYSBjbGVhcmVyCi0gICAg
ICAgIyBpbnRlcmZhY2UgdG8gd29yayB3aXRoIHRoYXQgd2lsbCBub3QgY2F1c2UgdGhpcyBpbmNv
bnNpc3RlbmN5LgotICAgICAgICMgICAtLSBBbmRyZXcgQmVubmV0dHMsIDIwMDYtMDktMjgKLSAg
ICAgICBzbWFydF9wcm90b2NvbC5hY2NlcHRfYnl0ZXMoJycpCi0gICAgICAgcmV0dXJuIHNtYXJ0
X3Byb3RvY29sCisgICAgICAgIG91dF9zdHJlYW0gPSBTdHJpbmdJTygpCisgICAgICAgIHNtYXJ0
X3Byb3RvY29sID0gcHJvdG9jb2wuU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoTm9uZSwg
b3V0X3N0cmVhbS53cml0ZSkKKyAgICAgICAgc21hcnRfcHJvdG9jb2wuaGFzX2Rpc3BhdGNoZWQg
PSBUcnVlCisgICAgICAgIHNtYXJ0X3Byb3RvY29sLnJlcXVlc3QgPSByZXF1ZXN0LlNtYXJ0U2Vy
dmVyUmVxdWVzdEhhbmRsZXIoTm9uZSkKKyAgICAgICAgZGVmIGhhbmRsZV9lbmRfb2ZfYnl0ZXMo
KToKKyAgICAgICAgICAgIHNlbGYuZW5kX3JlY2VpdmVkID0gVHJ1ZQorICAgICAgICAgICAgc2Vs
Zi5hc3NlcnRFcXVhbCgnYWJjZGVmZycsIHNtYXJ0X3Byb3RvY29sLnJlcXVlc3QuX2JvZHlfYnl0
ZXMpCisgICAgICAgICAgICBzbWFydF9wcm90b2NvbC5yZXF1ZXN0LnJlc3BvbnNlID0gcmVxdWVz
dC5TbWFydFNlcnZlclJlc3BvbnNlKCgnb2snLCApKQorICAgICAgICBzbWFydF9wcm90b2NvbC5y
ZXF1ZXN0Ll9lbmRfb2ZfYm9keV9oYW5kbGVyID0gaGFuZGxlX2VuZF9vZl9ieXRlcworICAgICAg
ICAjIENhbGwgYWNjZXB0X2J5dGVzIHRvIG1ha2Ugc3VyZSB0aGF0IGludGVybmFsIHN0YXRlIGxp
a2UgX2JvZHlfZGVjb2RlcgorICAgICAgICAjIGlzIGluaXRpYWxpc2VkLiAgVGhpcyB0ZXN0IHNo
b3VsZCBwcm9iYWJseSBiZSBnaXZlbiBhIGNsZWFyZXIKKyAgICAgICAgIyBpbnRlcmZhY2UgdG8g
d29yayB3aXRoIHRoYXQgd2lsbCBub3QgY2F1c2UgdGhpcyBpbmNvbnNpc3RlbmN5LgorICAgICAg
ICAjICAgLS0gQW5kcmV3IEJlbm5ldHRzLCAyMDA2LTA5LTI4CisgICAgICAgIHNtYXJ0X3Byb3Rv
Y29sLmFjY2VwdF9ieXRlcygnJykKKyAgICAgICAgcmV0dXJuIHNtYXJ0X3Byb3RvY29sCiAKICAg
ICBkZWYgdGVzdF9jb25zdHJ1Y3RfdmVyc2lvbl9vbmVfc2VydmVyX3Byb3RvY29sKHNlbGYpOgog
ICAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3RvY29sLlNtYXJ0U2VydmVyUmVxdWVzdFByb3Rv
Y29sT25lKE5vbmUsIE5vbmUpCgo=

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200704100
... 20914-rjhtq6bfcbrj2vjs
# revision id: andrew.bennetts at canonical.com-20070410020914-rjhtq6bfcbrj2vjs
# sha1: b1737133711e77d5926569b41bc643f71d3d1560
# inventory sha1: eccfb0561529a7105fbeb8509881920eeab3b8d4
# parent ids:
#   andrew.bennetts at canonical.com-20070409044955-h3ijql5cvqxia4d4
# properties:
#   branch-nick: split-smart-part-1-rename

# message:
#   Split smart transport code into several separate modules.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Mon 2007-04-09 14:49:55.503999949 +1000

=== modified file bzrlib/smart/medium.py // encoding:base64
LS0tIGJ6cmxpYi9zbWFydC9tZWRpdW0ucHkKKysrIGJ6cmxpYi9zbWFydC9tZWRpdW0ucHkKQEAg
LTAsMCArMSw1MjUgQEAKKyMgQ29weXJpZ2h0IChDKSAyMDA2LDIwMDcgQ2Fub25pY2FsIEx0ZAor
IworIyBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUg
aXQgYW5kL29yIG1vZGlmeQorIyBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFs
IFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQorIyB0aGUgRnJlZSBTb2Z0d2FyZSBGb3Vu
ZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorIyAoYXQgeW91ciBv
cHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgorIworIyBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0
ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyMgYnV0IFdJVEhPVVQgQU5Z
IFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKKyMgTUVSQ0hB
TlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQor
IyBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorIworIyBZb3Ug
c2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGlj
ZW5zZQorIyBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJl
ZSBTb2Z0d2FyZQorIyBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMz
MCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNyAgVVNBCisKKyIiIlRoZSAnbWVkaXVtJyBsYXllciBm
b3IgdGhlIHNtYXJ0IHNlcnZlcnMgYW5kIGNsaWVudHMuCisKKyJNZWRpdW0iIGhlcmUgaXMgdGhl
IG5vdW4gbWVhbmluZyAiYSBtZWFucyBvZiB0cmFuc21pc3Npb24iLCBub3QgdGhlIGFkamVjdGl2
ZQorZm9yICJ0aGUgcXVhbGl0eSBiZXR3ZWVuIGJpZyBhbmQgc21hbGwuIgorCitNZWRpYSBjYXJy
eSB0aGUgYnl0ZXMgb2YgdGhlIHJlcXVlc3RzIHNvbWVob3cgKGUuZy4gdmlhIFRDUCwgd3JhcHBl
ZCBpbiBIVFRQLCBvcgorb3ZlciBTU0gpLCBhbmQgcGFzcyB0aGVtIHRvIGFuZCBmcm9tIHRoZSBw
cm90b2NvbCBsb2dpYy4gIFNlZSB0aGUgb3ZlcnZpZXcgaW4KK2J6cmxpYi90cmFuc3BvcnQvc21h
cnQvX19pbml0X18ucHkuCisiIiIKKworaW1wb3J0IG9zCitpbXBvcnQgc29ja2V0CitpbXBvcnQg
c3lzCitmcm9tIGJ6cmxpYiBpbXBvcnQgZXJyb3JzCitmcm9tIGJ6cmxpYi5zbWFydC5wcm90b2Nv
bCBpbXBvcnQgU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUKKwordHJ5OgorICAgIGZyb20g
YnpybGliLnRyYW5zcG9ydCBpbXBvcnQgc3NoCitleGNlcHQgZXJyb3JzLlBhcmFtaWtvTm90UHJl
c2VudDoKKyAgICAjIG5vIHBhcmFtaWtvLiAgU21hcnRTU0hDbGllbnRNZWRpdW0gd2lsbCBicmVh
ay4KKyAgICBwYXNzCisKKworY2xhc3MgU21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0KG9iamVjdCk6
CisgICAgIiIiQSByZXF1ZXN0IG9uIGEgU21hcnRDbGllbnRNZWRpdW0uCisKKyAgICBFYWNoIHJl
cXVlc3QgYWxsb3dzIGJ5dGVzIHRvIGJlIHByb3ZpZGVkIHRvIGl0IHZpYSBhY2NlcHRfYnl0ZXMs
IGFuZCB0aGVuCisgICAgdGhlIHJlc3BvbnNlIGJ5dGVzIHRvIGJlIHJlYWQgdmlhIHJlYWRfYnl0
ZXMuCisKKyAgICBGb3IgaW5zdGFuY2U6CisgICAgcmVxdWVzdC5hY2NlcHRfYnl0ZXMoJzEyMycp
CisgICAgcmVxdWVzdC5maW5pc2hlZF93cml0aW5nKCkKKyAgICByZXN1bHQgPSByZXF1ZXN0LnJl
YWRfYnl0ZXMoMykKKyAgICByZXF1ZXN0LmZpbmlzaGVkX3JlYWRpbmcoKQorCisgICAgSXQgaXMg
dXAgdG8gdGhlIGluZGl2aWR1YWwgU21hcnRDbGllbnRNZWRpdW0gd2hldGhlciBtdWx0aXBsZSBj
b25jdXJyZW50CisgICAgcmVxdWVzdHMgY2FuIGV4aXN0LiBTZWUgU21hcnRDbGllbnRNZWRpdW0u
Z2V0X3JlcXVlc3QgdG8gb2J0YWluIGluc3RhbmNlcyAKKyAgICBvZiBTbWFydENsaWVudE1lZGl1
bVJlcXVlc3QsIGFuZCB0aGUgY29uY3JldGUgTWVkaXVtIHlvdSBhcmUgdXNpbmcgZm9yIAorICAg
IGRldGFpbHMgb24gY29uY3VycmVuY3kgYW5kIHBpcGVsaW5pbmcuCisgICAgIiIiCisKKyAgICBk
ZWYgX19pbml0X18oc2VsZiwgbWVkaXVtKToKKyAgICAgICAgIiIiQ29uc3RydWN0IGEgU21hcnRD
bGllbnRNZWRpdW1SZXF1ZXN0IGZvciB0aGUgbWVkaXVtIG1lZGl1bS4iIiIKKyAgICAgICAgc2Vs
Zi5fbWVkaXVtID0gbWVkaXVtCisgICAgICAgICMgd2UgdHJhY2sgc3RhdGUgYnkgY29uc3RhbnRz
IC0gd2UgbWF5IHdhbnQgdG8gdXNlIHRoZSBzYW1lCisgICAgICAgICMgcGF0dGVybiBhcyBCb2R5
UmVhZGVyIGlmIGl0IGdldHMgbW9yZSBjb21wbGV4LgorICAgICAgICAjIHZhbGlkIHN0YXRlcyBh
cmU6ICJ3cml0aW5nIiwgInJlYWRpbmciLCAiZG9uZSIKKyAgICAgICAgc2VsZi5fc3RhdGUgPSAi
d3JpdGluZyIKKworICAgIGRlZiBhY2NlcHRfYnl0ZXMoc2VsZiwgYnl0ZXMpOgorICAgICAgICAi
IiJBY2NlcHQgYnl0ZXMgZm9yIGluY2x1c2lvbiBpbiB0aGlzIHJlcXVlc3QuCisKKyAgICAgICAg
VGhpcyBtZXRob2QgbWF5IG5vdCBiZSBiZSBjYWxsZWQgYWZ0ZXIgZmluaXNoZWRfd3JpdGluZygp
IGhhcyBiZWVuCisgICAgICAgIGNhbGxlZC4gIEl0IGRlcGVuZHMgdXBvbiB0aGUgTWVkaXVtIHdo
ZXRoZXIgb3Igbm90IHRoZSBieXRlcyB3aWxsIGJlCisgICAgICAgIGltbWVkaWF0ZWx5IHRyYW5z
bWl0dGVkLiBNZXNzYWdlIGJhc2VkIE1lZGl1bXMgd2lsbCB0ZW5kIHRvIGJ1ZmZlciB0aGUKKyAg
ICAgICAgYnl0ZXMgdW50aWwgZmluaXNoZWRfd3JpdGluZygpIGlzIGNhbGxlZC4KKworICAgICAg
ICA6cGFyYW0gYnl0ZXM6IEEgYnl0ZXN0cmluZy4KKyAgICAgICAgIiIiCisgICAgICAgIGlmIHNl
bGYuX3N0YXRlICE9ICJ3cml0aW5nIjoKKyAgICAgICAgICAgIHJhaXNlIGVycm9ycy5Xcml0aW5n
Q29tcGxldGVkKHNlbGYpCisgICAgICAgIHNlbGYuX2FjY2VwdF9ieXRlcyhieXRlcykKKworICAg
IGRlZiBfYWNjZXB0X2J5dGVzKHNlbGYsIGJ5dGVzKToKKyAgICAgICAgIiIiSGVscGVyIGZvciBh
Y2NlcHRfYnl0ZXMuCisKKyAgICAgICAgQWNjZXB0X2J5dGVzIGNoZWNrcyB0aGUgc3RhdGUgb2Yg
dGhlIHJlcXVlc3QgdG8gZGV0ZXJtaW5nIGlmIGJ5dGVzCisgICAgICAgIHNob3VsZCBiZSBhY2Nl
cHRlZC4gQWZ0ZXIgdGhhdCBpdCBoYW5kcyBvZmYgdG8gX2FjY2VwdF9ieXRlcyB0byBkbyB0aGUK
KyAgICAgICAgYWN0dWFsIGFjY2VwdGFuY2UuCisgICAgICAgICIiIgorICAgICAgICByYWlzZSBO
b3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuX2FjY2VwdF9ieXRlcykKKworICAgIGRlZiBmaW5pc2hl
ZF9yZWFkaW5nKHNlbGYpOgorICAgICAgICAiIiJJbmZvcm0gdGhlIHJlcXVlc3QgdGhhdCBhbGwg
ZGVzaXJlZCBkYXRhIGhhcyBiZWVuIHJlYWQuCisKKyAgICAgICAgVGhpcyB3aWxsIHJlbW92ZSB0
aGUgcmVxdWVzdCBmcm9tIHRoZSBwaXBlbGluZSBmb3IgaXRzIG1lZGl1bSAoaWYgdGhlCisgICAg
ICAgIG1lZGl1bSBzdXBwb3J0cyBwaXBlbGluaW5nKSBhbmQgYW55IGZ1cnRoZXIgY2FsbHMgdG8g
bWV0aG9kcyBvbiB0aGUKKyAgICAgICAgcmVxdWVzdCB3aWxsIHJhaXNlIFJlYWRpbmdDb21wbGV0
ZWQuCisgICAgICAgICIiIgorICAgICAgICBpZiBzZWxmLl9zdGF0ZSA9PSAid3JpdGluZyI6Cisg
ICAgICAgICAgICByYWlzZSBlcnJvcnMuV3JpdGluZ05vdENvbXBsZXRlKHNlbGYpCisgICAgICAg
IGlmIHNlbGYuX3N0YXRlICE9ICJyZWFkaW5nIjoKKyAgICAgICAgICAgIHJhaXNlIGVycm9ycy5S
ZWFkaW5nQ29tcGxldGVkKHNlbGYpCisgICAgICAgIHNlbGYuX3N0YXRlID0gImRvbmUiCisgICAg
ICAgIHNlbGYuX2ZpbmlzaGVkX3JlYWRpbmcoKQorCisgICAgZGVmIF9maW5pc2hlZF9yZWFkaW5n
KHNlbGYpOgorICAgICAgICAiIiJIZWxwZXIgZm9yIGZpbmlzaGVkX3JlYWRpbmcuCisKKyAgICAg
ICAgZmluaXNoZWRfcmVhZGluZyBjaGVja3MgdGhlIHN0YXRlIG9mIHRoZSByZXF1ZXN0IHRvIGRl
dGVybWluZSBpZiAKKyAgICAgICAgZmluaXNoZWRfcmVhZGluZyBpcyBhbGxvd2VkLCBhbmQgaWYg
aXQgaXMgaGFuZHMgb2ZmIHRvIF9maW5pc2hlZF9yZWFkaW5nCisgICAgICAgIHRvIHBlcmZvcm0g
dGhlIGFjdGlvbi4KKyAgICAgICAgIiIiCisgICAgICAgIHJhaXNlIE5vdEltcGxlbWVudGVkRXJy
b3Ioc2VsZi5fZmluaXNoZWRfcmVhZGluZykKKworICAgIGRlZiBmaW5pc2hlZF93cml0aW5nKHNl
bGYpOgorICAgICAgICAiIiJGaW5pc2ggdGhlIHdyaXRpbmcgcGhhc2Ugb2YgdGhpcyByZXF1ZXN0
LgorCisgICAgICAgIFRoaXMgd2lsbCBmbHVzaCBhbGwgcGVuZGluZyBkYXRhIGZvciB0aGlzIHJl
cXVlc3QgYWxvbmcgdGhlIG1lZGl1bS4KKyAgICAgICAgQWZ0ZXIgY2FsbGluZyBmaW5pc2hlZF93
cml0aW5nLCB5b3UgbWF5IG5vdCBjYWxsIGFjY2VwdF9ieXRlcyBhbnltb3JlLgorICAgICAgICAi
IiIKKyAgICAgICAgaWYgc2VsZi5fc3RhdGUgIT0gIndyaXRpbmciOgorICAgICAgICAgICAgcmFp
c2UgZXJyb3JzLldyaXRpbmdDb21wbGV0ZWQoc2VsZikKKyAgICAgICAgc2VsZi5fc3RhdGUgPSAi
cmVhZGluZyIKKyAgICAgICAgc2VsZi5fZmluaXNoZWRfd3JpdGluZygpCisKKyAgICBkZWYgX2Zp
bmlzaGVkX3dyaXRpbmcoc2VsZik6CisgICAgICAgICIiIkhlbHBlciBmb3IgZmluaXNoZWRfd3Jp
dGluZy4KKworICAgICAgICBmaW5pc2hlZF93cml0aW5nIGNoZWNrcyB0aGUgc3RhdGUgb2YgdGhl
IHJlcXVlc3QgdG8gZGV0ZXJtaW5lIGlmIAorICAgICAgICBmaW5pc2hlZF93cml0aW5nIGlzIGFs
bG93ZWQsIGFuZCBpZiBpdCBpcyBoYW5kcyBvZmYgdG8gX2ZpbmlzaGVkX3dyaXRpbmcKKyAgICAg
ICAgdG8gcGVyZm9ybSB0aGUgYWN0aW9uLgorICAgICAgICAiIiIKKyAgICAgICAgcmFpc2UgTm90
SW1wbGVtZW50ZWRFcnJvcihzZWxmLl9maW5pc2hlZF93cml0aW5nKQorCisgICAgZGVmIHJlYWRf
Ynl0ZXMoc2VsZiwgY291bnQpOgorICAgICAgICAiIiJSZWFkIGJ5dGVzIGZyb20gdGhpcyByZXF1
ZXN0cyByZXNwb25zZS4KKworICAgICAgICBUaGlzIG1ldGhvZCB3aWxsIGJsb2NrIGFuZCB3YWl0
IGZvciBjb3VudCBieXRlcyB0byBiZSByZWFkLiBJdCBtYXkgbm90CisgICAgICAgIGJlIGludm9r
ZWQgdW50aWwgZmluaXNoZWRfd3JpdGluZygpIGhhcyBiZWVuIGNhbGxlZCAtIHRoaXMgaXMgdG8g
ZW5zdXJlCisgICAgICAgIGEgbWVzc2FnZS1iYXNlZCBhcHByb2FjaCB0byByZXF1ZXN0cywgZm9y
IGNvbXBhdGFiaWxpdHkgd2l0aCBtZXNzYWdlCisgICAgICAgIGJhc2VkIG1lZGl1bXMgbGlrZSBI
VFRQLgorICAgICAgICAiIiIKKyAgICAgICAgaWYgc2VsZi5fc3RhdGUgPT0gIndyaXRpbmciOgor
ICAgICAgICAgICAgcmFpc2UgZXJyb3JzLldyaXRpbmdOb3RDb21wbGV0ZShzZWxmKQorICAgICAg
ICBpZiBzZWxmLl9zdGF0ZSAhPSAicmVhZGluZyI6CisgICAgICAgICAgICByYWlzZSBlcnJvcnMu
UmVhZGluZ0NvbXBsZXRlZChzZWxmKQorICAgICAgICByZXR1cm4gc2VsZi5fcmVhZF9ieXRlcyhj
b3VudCkKKworICAgIGRlZiBfcmVhZF9ieXRlcyhzZWxmLCBjb3VudCk6CisgICAgICAgICIiIkhl
bHBlciBmb3IgcmVhZF9ieXRlcy4KKworICAgICAgICByZWFkX2J5dGVzIGNoZWNrcyB0aGUgc3Rh
dGUgb2YgdGhlIHJlcXVlc3QgdG8gZGV0ZXJtaW5nIGlmIGJ5dGVzCisgICAgICAgIHNob3VsZCBi
ZSByZWFkLiBBZnRlciB0aGF0IGl0IGhhbmRzIG9mZiB0byBfcmVhZF9ieXRlcyB0byBkbyB0aGUK
KyAgICAgICAgYWN0dWFsIHJlYWQuCisgICAgICAgICIiIgorICAgICAgICByYWlzZSBOb3RJbXBs
ZW1lbnRlZEVycm9yKHNlbGYuX3JlYWRfYnl0ZXMpCisKKworY2xhc3MgU21hcnRDbGllbnRTdHJl
YW1NZWRpdW1SZXF1ZXN0KFNtYXJ0Q2xpZW50TWVkaXVtUmVxdWVzdCk6CisgICAgIiIiQSBTbWFy
dENsaWVudE1lZGl1bVJlcXVlc3QgdGhhdCB3b3JrcyB3aXRoIGFuIFNtYXJ0Q2xpZW50U3RyZWFt
TWVkaXVtLiIiIgorCisgICAgZGVmIF9faW5pdF9fKHNlbGYsIG1lZGl1bSk6CisgICAgICAgIFNt
YXJ0Q2xpZW50TWVkaXVtUmVxdWVzdC5fX2luaXRfXyhzZWxmLCBtZWRpdW0pCisgICAgICAgICMg
Y2hlY2sgdGhhdCB3ZSBhcmUgc2FmZSBjb25jdXJyZW5jeSB3aXNlLiBJZiBzb21lIHN0cmVhbXMg
c3RhcnQKKyAgICAgICAgIyBhbGxvd2luZyBjb25jdXJyZW50IHJlcXVlc3RzIC0gaS5lLiB2aWEg
bXVsdGlwbGV4aW5nIC0gdGhlbiB0aGlzCisgICAgICAgICMgYXNzZXJ0IHNob3VsZCBiZSBtb3Zl
ZCB0byBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5nZXRfcmVxdWVzdCwKKyAgICAgICAgIyBhbmQg
dGhlIHNldHRpbmcvdW5zZXR0aW5nIG9mIF9jdXJyZW50X3JlcXVlc3QgbGlrZXdpc2UgbW92ZWQg
aW50bworICAgICAgICAjIHRoYXQgY2xhc3MgOiBidXQgaXRzIHVubmVlZGVkIG92ZXJoZWFkIGZv
ciBub3cuIFJCQyAyMDA2MDkyMgorICAgICAgICBpZiBzZWxmLl9tZWRpdW0uX2N1cnJlbnRfcmVx
dWVzdCBpcyBub3QgTm9uZToKKyAgICAgICAgICAgIHJhaXNlIGVycm9ycy5Ub29NYW55Q29uY3Vy
cmVudFJlcXVlc3RzKHNlbGYuX21lZGl1bSkKKyAgICAgICAgc2VsZi5fbWVkaXVtLl9jdXJyZW50
X3JlcXVlc3QgPSBzZWxmCisKKyAgICBkZWYgX2FjY2VwdF9ieXRlcyhzZWxmLCBieXRlcyk6Cisg
ICAgICAgICIiIlNlZSBTbWFydENsaWVudE1lZGl1bVJlcXVlc3QuX2FjY2VwdF9ieXRlcy4KKyAg
ICAgICAgCisgICAgICAgIFRoaXMgZm9yd2FyZHMgdG8gc2VsZi5fbWVkaXVtLl9hY2NlcHRfYnl0
ZXMgYmVjYXVzZSB3ZSBhcmUgb3BlcmF0aW5nCisgICAgICAgIG9uIHRoZSBtZWRpdW1zIHN0cmVh
bS4KKyAgICAgICAgIiIiCisgICAgICAgIHNlbGYuX21lZGl1bS5fYWNjZXB0X2J5dGVzKGJ5dGVz
KQorCisgICAgZGVmIF9maW5pc2hlZF9yZWFkaW5nKHNlbGYpOgorICAgICAgICAiIiJTZWUgU21h
cnRDbGllbnRNZWRpdW1SZXF1ZXN0Ll9maW5pc2hlZF9yZWFkaW5nLgorCisgICAgICAgIFRoaXMg
Y2xlYXJzIHRoZSBfY3VycmVudF9yZXF1ZXN0IG9uIHNlbGYuX21lZGl1bSB0byBhbGxvdyBhIG5l
dyAKKyAgICAgICAgcmVxdWVzdCB0byBiZSBjcmVhdGVkLgorICAgICAgICAiIiIKKyAgICAgICAg
YXNzZXJ0IHNlbGYuX21lZGl1bS5fY3VycmVudF9yZXF1ZXN0IGlzIHNlbGYKKyAgICAgICAgc2Vs
Zi5fbWVkaXVtLl9jdXJyZW50X3JlcXVlc3QgPSBOb25lCisgICAgICAgIAorICAgIGRlZiBfZmlu
aXNoZWRfd3JpdGluZyhzZWxmKToKKyAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50TWVkaXVtUmVx
dWVzdC5fZmluaXNoZWRfd3JpdGluZy4KKworICAgICAgICBUaGlzIGludm9rZXMgc2VsZi5fbWVk
aXVtLl9mbHVzaCB0byBlbnN1cmUgYWxsIGJ5dGVzIGFyZSB0cmFuc21pdHRlZC4KKyAgICAgICAg
IiIiCisgICAgICAgIHNlbGYuX21lZGl1bS5fZmx1c2goKQorCisgICAgZGVmIF9yZWFkX2J5dGVz
KHNlbGYsIGNvdW50KToKKyAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50TWVkaXVtUmVxdWVzdC5f
cmVhZF9ieXRlcy4KKyAgICAgICAgCisgICAgICAgIFRoaXMgZm9yd2FyZHMgdG8gc2VsZi5fbWVk
aXVtLl9yZWFkX2J5dGVzIGJlY2F1c2Ugd2UgYXJlIG9wZXJhdGluZworICAgICAgICBvbiB0aGUg
bWVkaXVtcyBzdHJlYW0uCisgICAgICAgICIiIgorICAgICAgICByZXR1cm4gc2VsZi5fbWVkaXVt
Ll9yZWFkX2J5dGVzKGNvdW50KQorCisKK2NsYXNzIFNtYXJ0U2VydmVyU3RyZWFtTWVkaXVtKG9i
amVjdCk6CisgICAgIiIiSGFuZGxlcyBzbWFydCBjb21tYW5kcyBjb21pbmcgb3ZlciBhIHN0cmVh
bS4KKworICAgIFRoZSBzdHJlYW0gbWF5IGJlIGEgcGlwZSBjb25uZWN0ZWQgdG8gc3NoZCwgb3Ig
YSB0Y3Agc29ja2V0LCBvciBhbgorICAgIGluLXByb2Nlc3MgZmlmbyBmb3IgdGVzdGluZy4KKwor
ICAgIE9uZSBpbnN0YW5jZSBpcyBjcmVhdGVkIGZvciBlYWNoIGNvbm5lY3RlZCBjbGllbnQ7IGl0
IGNhbiBzZXJ2ZSBtdWx0aXBsZQorICAgIHJlcXVlc3RzIGluIHRoZSBsaWZldGltZSBvZiB0aGUg
Y29ubmVjdGlvbi4KKworICAgIFRoZSBzZXJ2ZXIgcGFzc2VzIHJlcXVlc3RzIHRocm91Z2ggdG8g
YW4gdW5kZXJseWluZyBiYWNraW5nIHRyYW5zcG9ydCwgCisgICAgd2hpY2ggd2lsbCB0eXBpY2Fs
bHkgYmUgYSBMb2NhbFRyYW5zcG9ydCBsb29raW5nIGF0IHRoZSBzZXJ2ZXIncyBmaWxlc3lzdGVt
LgorICAgICIiIgorCisgICAgZGVmIF9faW5pdF9fKHNlbGYsIGJhY2tpbmdfdHJhbnNwb3J0KToK
KyAgICAgICAgIiIiQ29uc3RydWN0IG5ldyBzZXJ2ZXIuCisKKyAgICAgICAgOnBhcmFtIGJhY2tp
bmdfdHJhbnNwb3J0OiBUcmFuc3BvcnQgZm9yIHRoZSBkaXJlY3Rvcnkgc2VydmVkLgorICAgICAg
ICAiIiIKKyAgICAgICAgIyBiYWNraW5nX3RyYW5zcG9ydCBjb3VsZCBiZSBwYXNzZWQgdG8gc2Vy
dmUgaW5zdGVhZCBvZiBfX2luaXRfXworICAgICAgICBzZWxmLmJhY2tpbmdfdHJhbnNwb3J0ID0g
YmFja2luZ190cmFuc3BvcnQKKyAgICAgICAgc2VsZi5maW5pc2hlZCA9IEZhbHNlCisKKyAgICBk
ZWYgc2VydmUoc2VsZik6CisgICAgICAgICIiIlNlcnZlIHJlcXVlc3RzIHVudGlsIHRoZSBjbGll
bnQgZGlzY29ubmVjdHMuIiIiCisgICAgICAgICMgS2VlcCBhIHJlZmVyZW5jZSB0byBzdGRlcnIg
YmVjYXVzZSB0aGUgc3lzIG1vZHVsZSdzIGdsb2JhbHMgZ2V0IHNldCB0bworICAgICAgICAjIE5v
bmUgZHVyaW5nIGludGVycHJldGVyIHNodXRkb3duLgorICAgICAgICBmcm9tIHN5cyBpbXBvcnQg
c3RkZXJyCisgICAgICAgIHRyeToKKyAgICAgICAgICAgIHdoaWxlIG5vdCBzZWxmLmZpbmlzaGVk
OgorICAgICAgICAgICAgICAgIHByb3RvY29sID0gU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xP
bmUoc2VsZi5iYWNraW5nX3RyYW5zcG9ydCwKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3dyaXRlX291dCkKKyAgICAgICAgICAg
ICAgICBzZWxmLl9zZXJ2ZV9vbmVfcmVxdWVzdChwcm90b2NvbCkKKyAgICAgICAgZXhjZXB0IEV4
Y2VwdGlvbiwgZToKKyAgICAgICAgICAgIHN0ZGVyci53cml0ZSgiJXMgdGVybWluYXRpbmcgb24g
ZXhjZXB0aW9uICVzXG4iICUgKHNlbGYsIGUpKQorICAgICAgICAgICAgcmFpc2UKKworICAgIGRl
ZiBfc2VydmVfb25lX3JlcXVlc3Qoc2VsZiwgcHJvdG9jb2wpOgorICAgICAgICAiIiJSZWFkIG9u
ZSByZXF1ZXN0IGZyb20gaW5wdXQsIHByb2Nlc3MsIHNlbmQgYmFjayBhIHJlc3BvbnNlLgorICAg
ICAgICAKKyAgICAgICAgOnBhcmFtIHByb3RvY29sOiBhIFNtYXJ0U2VydmVyUmVxdWVzdFByb3Rv
Y29sLgorICAgICAgICAiIiIKKyAgICAgICAgdHJ5OgorICAgICAgICAgICAgc2VsZi5fc2VydmVf
b25lX3JlcXVlc3RfdW5ndWFyZGVkKHByb3RvY29sKQorICAgICAgICBleGNlcHQgS2V5Ym9hcmRJ
bnRlcnJ1cHQ6CisgICAgICAgICAgICByYWlzZQorICAgICAgICBleGNlcHQgRXhjZXB0aW9uLCBl
OgorICAgICAgICAgICAgc2VsZi50ZXJtaW5hdGVfZHVlX3RvX2Vycm9yKCkKKworICAgIGRlZiB0
ZXJtaW5hdGVfZHVlX3RvX2Vycm9yKHNlbGYpOgorICAgICAgICAiIiJDYWxsZWQgd2hlbiBhbiB1
bmhhbmRsZWQgZXhjZXB0aW9uIGZyb20gdGhlIHByb3RvY29sIG9jY3Vycy4iIiIKKyAgICAgICAg
cmFpc2UgTm90SW1wbGVtZW50ZWRFcnJvcihzZWxmLnRlcm1pbmF0ZV9kdWVfdG9fZXJyb3IpCisK
KworY2xhc3MgU21hcnRTZXJ2ZXJTb2NrZXRTdHJlYW1NZWRpdW0oU21hcnRTZXJ2ZXJTdHJlYW1N
ZWRpdW0pOgorCisgICAgZGVmIF9faW5pdF9fKHNlbGYsIHNvY2ssIGJhY2tpbmdfdHJhbnNwb3J0
KToKKyAgICAgICAgIiIiQ29uc3RydWN0b3IuCisKKyAgICAgICAgOnBhcmFtIHNvY2s6IHRoZSBz
b2NrZXQgdGhlIHNlcnZlciB3aWxsIHJlYWQgZnJvbS4gIEl0IHdpbGwgYmUgcHV0CisgICAgICAg
ICAgICBpbnRvIGJsb2NraW5nIG1vZGUuCisgICAgICAgICIiIgorICAgICAgICBTbWFydFNlcnZl
clN0cmVhbU1lZGl1bS5fX2luaXRfXyhzZWxmLCBiYWNraW5nX3RyYW5zcG9ydCkKKyAgICAgICAg
c2VsZi5wdXNoX2JhY2sgPSAnJworICAgICAgICBzb2NrLnNldGJsb2NraW5nKFRydWUpCisgICAg
ICAgIHNlbGYuc29ja2V0ID0gc29jaworCisgICAgZGVmIF9zZXJ2ZV9vbmVfcmVxdWVzdF91bmd1
YXJkZWQoc2VsZiwgcHJvdG9jb2wpOgorICAgICAgICB3aGlsZSBwcm90b2NvbC5uZXh0X3JlYWRf
c2l6ZSgpOgorICAgICAgICAgICAgaWYgc2VsZi5wdXNoX2JhY2s6CisgICAgICAgICAgICAgICAg
cHJvdG9jb2wuYWNjZXB0X2J5dGVzKHNlbGYucHVzaF9iYWNrKQorICAgICAgICAgICAgICAgIHNl
bGYucHVzaF9iYWNrID0gJycKKyAgICAgICAgICAgIGVsc2U6CisgICAgICAgICAgICAgICAgYnl0
ZXMgPSBzZWxmLnNvY2tldC5yZWN2KDQwOTYpCisgICAgICAgICAgICAgICAgaWYgYnl0ZXMgPT0g
Jyc6CisgICAgICAgICAgICAgICAgICAgIHNlbGYuZmluaXNoZWQgPSBUcnVlCisgICAgICAgICAg
ICAgICAgICAgIHJldHVybgorICAgICAgICAgICAgICAgIHByb3RvY29sLmFjY2VwdF9ieXRlcyhi
eXRlcykKKyAgICAgICAgCisgICAgICAgIHNlbGYucHVzaF9iYWNrID0gcHJvdG9jb2wuZXhjZXNz
X2J1ZmZlcgorICAgIAorICAgIGRlZiB0ZXJtaW5hdGVfZHVlX3RvX2Vycm9yKHNlbGYpOgorICAg
ICAgICAiIiJDYWxsZWQgd2hlbiBhbiB1bmhhbmRsZWQgZXhjZXB0aW9uIGZyb20gdGhlIHByb3Rv
Y29sIG9jY3Vycy4iIiIKKyAgICAgICAgIyBUT0RPOiBUaGlzIHNob3VsZCBsb2cgdG8gYSBzZXJ2
ZXIgbG9nIGZpbGUsIGJ1dCBubyBzdWNoIHRoaW5nCisgICAgICAgICMgZXhpc3RzIHlldC4gIEFu
ZHJldyBCZW5uZXR0cyAyMDA2LTA5LTI5LgorICAgICAgICBzZWxmLnNvY2tldC5jbG9zZSgpCisg
ICAgICAgIHNlbGYuZmluaXNoZWQgPSBUcnVlCisKKyAgICBkZWYgX3dyaXRlX291dChzZWxmLCBi
eXRlcyk6CisgICAgICAgIHNlbGYuc29ja2V0LnNlbmRhbGwoYnl0ZXMpCisKKworY2xhc3MgU21h
cnRTZXJ2ZXJQaXBlU3RyZWFtTWVkaXVtKFNtYXJ0U2VydmVyU3RyZWFtTWVkaXVtKToKKworICAg
IGRlZiBfX2luaXRfXyhzZWxmLCBpbl9maWxlLCBvdXRfZmlsZSwgYmFja2luZ190cmFuc3BvcnQp
OgorICAgICAgICAiIiJDb25zdHJ1Y3QgbmV3IHNlcnZlci4KKworICAgICAgICA6cGFyYW0gaW5f
ZmlsZTogUHl0aG9uIGZpbGUgZnJvbSB3aGljaCByZXF1ZXN0cyBjYW4gYmUgcmVhZC4KKyAgICAg
ICAgOnBhcmFtIG91dF9maWxlOiBQeXRob24gZmlsZSB0byB3cml0ZSByZXNwb25zZXMuCisgICAg
ICAgIDpwYXJhbSBiYWNraW5nX3RyYW5zcG9ydDogVHJhbnNwb3J0IGZvciB0aGUgZGlyZWN0b3J5
IHNlcnZlZC4KKyAgICAgICAgIiIiCisgICAgICAgIFNtYXJ0U2VydmVyU3RyZWFtTWVkaXVtLl9f
aW5pdF9fKHNlbGYsIGJhY2tpbmdfdHJhbnNwb3J0KQorICAgICAgICBpZiBzeXMucGxhdGZvcm0g
PT0gJ3dpbjMyJzoKKyAgICAgICAgICAgICMgZm9yY2UgYmluYXJ5IG1vZGUgZm9yIGZpbGVzCisg
ICAgICAgICAgICBpbXBvcnQgbXN2Y3J0CisgICAgICAgICAgICBmb3IgZiBpbiAoaW5fZmlsZSwg
b3V0X2ZpbGUpOgorICAgICAgICAgICAgICAgIGZpbGVubyA9IGdldGF0dHIoZiwgJ2ZpbGVubycs
IE5vbmUpCisgICAgICAgICAgICAgICAgaWYgZmlsZW5vOgorICAgICAgICAgICAgICAgICAgICBt
c3ZjcnQuc2V0bW9kZShmaWxlbm8oKSwgb3MuT19CSU5BUlkpCisgICAgICAgIHNlbGYuX2luID0g
aW5fZmlsZQorICAgICAgICBzZWxmLl9vdXQgPSBvdXRfZmlsZQorCisgICAgZGVmIF9zZXJ2ZV9v
bmVfcmVxdWVzdF91bmd1YXJkZWQoc2VsZiwgcHJvdG9jb2wpOgorICAgICAgICB3aGlsZSBUcnVl
OgorICAgICAgICAgICAgYnl0ZXNfdG9fcmVhZCA9IHByb3RvY29sLm5leHRfcmVhZF9zaXplKCkK
KyAgICAgICAgICAgIGlmIGJ5dGVzX3RvX3JlYWQgPT0gMDoKKyAgICAgICAgICAgICAgICAjIEZp
bmlzaGVkIHNlcnZpbmcgdGhpcyByZXF1ZXN0LgorICAgICAgICAgICAgICAgIHNlbGYuX291dC5m
bHVzaCgpCisgICAgICAgICAgICAgICAgcmV0dXJuCisgICAgICAgICAgICBieXRlcyA9IHNlbGYu
X2luLnJlYWQoYnl0ZXNfdG9fcmVhZCkKKyAgICAgICAgICAgIGlmIGJ5dGVzID09ICcnOgorICAg
ICAgICAgICAgICAgICMgQ29ubmVjdGlvbiBoYXMgYmVlbiBjbG9zZWQuCisgICAgICAgICAgICAg
ICAgc2VsZi5maW5pc2hlZCA9IFRydWUKKyAgICAgICAgICAgICAgICBzZWxmLl9vdXQuZmx1c2go
KQorICAgICAgICAgICAgICAgIHJldHVybgorICAgICAgICAgICAgcHJvdG9jb2wuYWNjZXB0X2J5
dGVzKGJ5dGVzKQorCisgICAgZGVmIHRlcm1pbmF0ZV9kdWVfdG9fZXJyb3Ioc2VsZik6CisgICAg
ICAgICMgVE9ETzogVGhpcyBzaG91bGQgbG9nIHRvIGEgc2VydmVyIGxvZyBmaWxlLCBidXQgbm8g
c3VjaCB0aGluZworICAgICAgICAjIGV4aXN0cyB5ZXQuICBBbmRyZXcgQmVubmV0dHMgMjAwNi0w
OS0yOS4KKyAgICAgICAgc2VsZi5fb3V0LmNsb3NlKCkKKyAgICAgICAgc2VsZi5maW5pc2hlZCA9
IFRydWUKKworICAgIGRlZiBfd3JpdGVfb3V0KHNlbGYsIGJ5dGVzKToKKyAgICAgICAgc2VsZi5f
b3V0LndyaXRlKGJ5dGVzKQorCisKK2NsYXNzIFNtYXJ0Q2xpZW50TWVkaXVtKG9iamVjdCk6Cisg
ICAgIiIiU21hcnQgY2xpZW50IGlzIGEgbWVkaXVtIGZvciBzZW5kaW5nIHNtYXJ0IHByb3RvY29s
IHJlcXVlc3RzIG92ZXIuIiIiCisKKyAgICBkZWYgZGlzY29ubmVjdChzZWxmKToKKyAgICAgICAg
IiIiSWYgdGhpcyBtZWRpdW0gbWFpbnRhaW5zIGEgcGVyc2lzdGVudCBjb25uZWN0aW9uLCBjbG9z
ZSBpdC4KKyAgICAgICAgCisgICAgICAgIFRoZSBkZWZhdWx0IGltcGxlbWVudGF0aW9uIGRvZXMg
bm90aGluZy4KKyAgICAgICAgIiIiCisgICAgICAgIAorCitjbGFzcyBTbWFydENsaWVudFN0cmVh
bU1lZGl1bShTbWFydENsaWVudE1lZGl1bSk6CisgICAgIiIiU3RyZWFtIGJhc2VkIG1lZGl1bSBj
b21tb24gY2xhc3MuCisKKyAgICBTbWFydENsaWVudFN0cmVhbU1lZGl1bXMgb3BlcmF0ZSBvbiBh
IHN0cmVhbS4gQWxsIHN1YmNsYXNzZXMgdXNlIGEgY29tbW9uCisgICAgU21hcnRDbGllbnRTdHJl
YW1NZWRpdW1SZXF1ZXN0IGZvciB0aGVpciByZXF1ZXN0cywgYW5kIHNob3VsZCBpbXBsZW1lbnQK
KyAgICBfYWNjZXB0X2J5dGVzIGFuZCBfcmVhZF9ieXRlcyB0byBhbGxvdyB0aGUgcmVxdWVzdCBv
YmplY3RzIHRvIHNlbmQgYW5kCisgICAgcmVjZWl2ZSBieXRlcy4KKyAgICAiIiIKKworICAgIGRl
ZiBfX2luaXRfXyhzZWxmKToKKyAgICAgICAgc2VsZi5fY3VycmVudF9yZXF1ZXN0ID0gTm9uZQor
CisgICAgZGVmIGFjY2VwdF9ieXRlcyhzZWxmLCBieXRlcyk6CisgICAgICAgIHNlbGYuX2FjY2Vw
dF9ieXRlcyhieXRlcykKKworICAgIGRlZiBfX2RlbF9fKHNlbGYpOgorICAgICAgICAiIiJUaGUg
U21hcnRDbGllbnRTdHJlYW1NZWRpdW0ga25vd3MgaG93IHRvIGNsb3NlIHRoZSBzdHJlYW0gd2hl
biBpdCBpcworICAgICAgICBmaW5pc2hlZCB3aXRoIGl0LgorICAgICAgICAiIiIKKyAgICAgICAg
c2VsZi5kaXNjb25uZWN0KCkKKworICAgIGRlZiBfZmx1c2goc2VsZik6CisgICAgICAgICIiIkZs
dXNoIHRoZSBvdXRwdXQgc3RyZWFtLgorICAgICAgICAKKyAgICAgICAgVGhpcyBtZXRob2QgaXMg
dXNlZCBieSB0aGUgU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0IHRvIGVuc3VyZSB0aGF0
CisgICAgICAgIGFsbCBkYXRhIGZvciBhIHJlcXVlc3QgaXMgc2VudCwgdG8gYXZvaWQgbG9uZyB0
aW1lb3V0cyBvciBkZWFkbG9ja3MuCisgICAgICAgICIiIgorICAgICAgICByYWlzZSBOb3RJbXBs
ZW1lbnRlZEVycm9yKHNlbGYuX2ZsdXNoKQorCisgICAgZGVmIGdldF9yZXF1ZXN0KHNlbGYpOgor
ICAgICAgICAiIiJTZWUgU21hcnRDbGllbnRNZWRpdW0uZ2V0X3JlcXVlc3QoKS4KKworICAgICAg
ICBTbWFydENsaWVudFN0cmVhbU1lZGl1bSBhbHdheXMgcmV0dXJucyBhIFNtYXJ0Q2xpZW50U3Ry
ZWFtTWVkaXVtUmVxdWVzdAorICAgICAgICBmb3IgZ2V0X3JlcXVlc3QuCisgICAgICAgICIiIgor
ICAgICAgICByZXR1cm4gU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KHNlbGYpCisKKyAg
ICBkZWYgcmVhZF9ieXRlcyhzZWxmLCBjb3VudCk6CisgICAgICAgIHJldHVybiBzZWxmLl9yZWFk
X2J5dGVzKGNvdW50KQorCisKK2NsYXNzIFNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oU21h
cnRDbGllbnRTdHJlYW1NZWRpdW0pOgorICAgICIiIkEgY2xpZW50IG1lZGl1bSB1c2luZyBzaW1w
bGUgcGlwZXMuCisgICAgCisgICAgVGhpcyBjbGllbnQgZG9lcyBub3QgbWFuYWdlIHRoZSBwaXBl
czogaXQgYXNzdW1lcyB0aGV5IHdpbGwgYWx3YXlzIGJlIG9wZW4uCisgICAgIiIiCisKKyAgICBk
ZWYgX19pbml0X18oc2VsZiwgcmVhZGFibGVfcGlwZSwgd3JpdGVhYmxlX3BpcGUpOgorICAgICAg
ICBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5fX2luaXRfXyhzZWxmKQorICAgICAgICBzZWxmLl9y
ZWFkYWJsZV9waXBlID0gcmVhZGFibGVfcGlwZQorICAgICAgICBzZWxmLl93cml0ZWFibGVfcGlw
ZSA9IHdyaXRlYWJsZV9waXBlCisKKyAgICBkZWYgX2FjY2VwdF9ieXRlcyhzZWxmLCBieXRlcyk6
CisgICAgICAgICIiIlNlZSBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5hY2NlcHRfYnl0ZXMuIiIi
CisgICAgICAgIHNlbGYuX3dyaXRlYWJsZV9waXBlLndyaXRlKGJ5dGVzKQorCisgICAgZGVmIF9m
bHVzaChzZWxmKToKKyAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtLl9mbHVz
aCgpLiIiIgorICAgICAgICBzZWxmLl93cml0ZWFibGVfcGlwZS5mbHVzaCgpCisKKyAgICBkZWYg
X3JlYWRfYnl0ZXMoc2VsZiwgY291bnQpOgorICAgICAgICAiIiJTZWUgU21hcnRDbGllbnRTdHJl
YW1NZWRpdW0uX3JlYWRfYnl0ZXMuIiIiCisgICAgICAgIHJldHVybiBzZWxmLl9yZWFkYWJsZV9w
aXBlLnJlYWQoY291bnQpCisKKworY2xhc3MgU21hcnRTU0hDbGllbnRNZWRpdW0oU21hcnRDbGll
bnRTdHJlYW1NZWRpdW0pOgorICAgICIiIkEgY2xpZW50IG1lZGl1bSB1c2luZyBTU0guIiIiCisg
ICAgCisgICAgZGVmIF9faW5pdF9fKHNlbGYsIGhvc3QsIHBvcnQ9Tm9uZSwgdXNlcm5hbWU9Tm9u
ZSwgcGFzc3dvcmQ9Tm9uZSwKKyAgICAgICAgICAgIHZlbmRvcj1Ob25lKToKKyAgICAgICAgIiIi
Q3JlYXRlcyBhIGNsaWVudCB0aGF0IHdpbGwgY29ubmVjdCBvbiB0aGUgZmlyc3QgdXNlLgorICAg
ICAgICAKKyAgICAgICAgOnBhcmFtIHZlbmRvcjogQW4gb3B0aW9uYWwgb3ZlcnJpZGUgZm9yIHRo
ZSBzc2ggdmVuZG9yIHRvIHVzZS4gU2VlCisgICAgICAgICAgICBienJsaWIudHJhbnNwb3J0LnNz
aCBmb3IgZGV0YWlscyBvbiBzc2ggdmVuZG9ycy4KKyAgICAgICAgIiIiCisgICAgICAgIFNtYXJ0
Q2xpZW50U3RyZWFtTWVkaXVtLl9faW5pdF9fKHNlbGYpCisgICAgICAgIHNlbGYuX2Nvbm5lY3Rl
ZCA9IEZhbHNlCisgICAgICAgIHNlbGYuX2hvc3QgPSBob3N0CisgICAgICAgIHNlbGYuX3Bhc3N3
b3JkID0gcGFzc3dvcmQKKyAgICAgICAgc2VsZi5fcG9ydCA9IHBvcnQKKyAgICAgICAgc2VsZi5f
dXNlcm5hbWUgPSB1c2VybmFtZQorICAgICAgICBzZWxmLl9yZWFkX2Zyb20gPSBOb25lCisgICAg
ICAgIHNlbGYuX3NzaF9jb25uZWN0aW9uID0gTm9uZQorICAgICAgICBzZWxmLl92ZW5kb3IgPSB2
ZW5kb3IKKyAgICAgICAgc2VsZi5fd3JpdGVfdG8gPSBOb25lCisKKyAgICBkZWYgX2FjY2VwdF9i
eXRlcyhzZWxmLCBieXRlcyk6CisgICAgICAgICIiIlNlZSBTbWFydENsaWVudFN0cmVhbU1lZGl1
bS5hY2NlcHRfYnl0ZXMuIiIiCisgICAgICAgIHNlbGYuX2Vuc3VyZV9jb25uZWN0aW9uKCkKKyAg
ICAgICAgc2VsZi5fd3JpdGVfdG8ud3JpdGUoYnl0ZXMpCisKKyAgICBkZWYgZGlzY29ubmVjdChz
ZWxmKToKKyAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50TWVkaXVtLmRpc2Nvbm5lY3QoKS4iIiIK
KyAgICAgICAgaWYgbm90IHNlbGYuX2Nvbm5lY3RlZDoKKyAgICAgICAgICAgIHJldHVybgorICAg
ICAgICBzZWxmLl9yZWFkX2Zyb20uY2xvc2UoKQorICAgICAgICBzZWxmLl93cml0ZV90by5jbG9z
ZSgpCisgICAgICAgIHNlbGYuX3NzaF9jb25uZWN0aW9uLmNsb3NlKCkKKyAgICAgICAgc2VsZi5f
Y29ubmVjdGVkID0gRmFsc2UKKworICAgIGRlZiBfZW5zdXJlX2Nvbm5lY3Rpb24oc2VsZik6Cisg
ICAgICAgICIiIkNvbm5lY3QgdGhpcyBtZWRpdW0gaWYgbm90IGFscmVhZHkgY29ubmVjdGVkLiIi
IgorICAgICAgICBpZiBzZWxmLl9jb25uZWN0ZWQ6CisgICAgICAgICAgICByZXR1cm4KKyAgICAg
ICAgZXhlY3V0YWJsZSA9IG9zLmVudmlyb24uZ2V0KCdCWlJfUkVNT1RFX1BBVEgnLCAnYnpyJykK
KyAgICAgICAgaWYgc2VsZi5fdmVuZG9yIGlzIE5vbmU6CisgICAgICAgICAgICB2ZW5kb3IgPSBz
c2guX2dldF9zc2hfdmVuZG9yKCkKKyAgICAgICAgZWxzZToKKyAgICAgICAgICAgIHZlbmRvciA9
IHNlbGYuX3ZlbmRvcgorICAgICAgICBzZWxmLl9zc2hfY29ubmVjdGlvbiA9IHZlbmRvci5jb25u
ZWN0X3NzaChzZWxmLl91c2VybmFtZSwKKyAgICAgICAgICAgICAgICBzZWxmLl9wYXNzd29yZCwg
c2VsZi5faG9zdCwgc2VsZi5fcG9ydCwKKyAgICAgICAgICAgICAgICBjb21tYW5kPVtleGVjdXRh
YmxlLCAnc2VydmUnLCAnLS1pbmV0JywgJy0tZGlyZWN0b3J5PS8nLAorICAgICAgICAgICAgICAg
ICAgICAgICAgICctLWFsbG93LXdyaXRlcyddKQorICAgICAgICBzZWxmLl9yZWFkX2Zyb20sIHNl
bGYuX3dyaXRlX3RvID0gXAorICAgICAgICAgICAgc2VsZi5fc3NoX2Nvbm5lY3Rpb24uZ2V0X2Zp
bGVsaWtlX2NoYW5uZWxzKCkKKyAgICAgICAgc2VsZi5fY29ubmVjdGVkID0gVHJ1ZQorCisgICAg
ZGVmIF9mbHVzaChzZWxmKToKKyAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVt
Ll9mbHVzaCgpLiIiIgorICAgICAgICBzZWxmLl93cml0ZV90by5mbHVzaCgpCisKKyAgICBkZWYg
X3JlYWRfYnl0ZXMoc2VsZiwgY291bnQpOgorICAgICAgICAiIiJTZWUgU21hcnRDbGllbnRTdHJl
YW1NZWRpdW0ucmVhZF9ieXRlcy4iIiIKKyAgICAgICAgaWYgbm90IHNlbGYuX2Nvbm5lY3RlZDoK
KyAgICAgICAgICAgIHJhaXNlIGVycm9ycy5NZWRpdW1Ob3RDb25uZWN0ZWQoc2VsZikKKyAgICAg
ICAgcmV0dXJuIHNlbGYuX3JlYWRfZnJvbS5yZWFkKGNvdW50KQorCisKK2NsYXNzIFNtYXJ0VENQ
Q2xpZW50TWVkaXVtKFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtKToKKyAgICAiIiJBIGNsaWVudCBt
ZWRpdW0gdXNpbmcgVENQLiIiIgorICAgIAorICAgIGRlZiBfX2luaXRfXyhzZWxmLCBob3N0LCBw
b3J0KToKKyAgICAgICAgIiIiQ3JlYXRlcyBhIGNsaWVudCB0aGF0IHdpbGwgY29ubmVjdCBvbiB0
aGUgZmlyc3QgdXNlLiIiIgorICAgICAgICBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5fX2luaXRf
XyhzZWxmKQorICAgICAgICBzZWxmLl9jb25uZWN0ZWQgPSBGYWxzZQorICAgICAgICBzZWxmLl9o
b3N0ID0gaG9zdAorICAgICAgICBzZWxmLl9wb3J0ID0gcG9ydAorICAgICAgICBzZWxmLl9zb2Nr
ZXQgPSBOb25lCisKKyAgICBkZWYgX2FjY2VwdF9ieXRlcyhzZWxmLCBieXRlcyk6CisgICAgICAg
ICIiIlNlZSBTbWFydENsaWVudE1lZGl1bS5hY2NlcHRfYnl0ZXMuIiIiCisgICAgICAgIHNlbGYu
X2Vuc3VyZV9jb25uZWN0aW9uKCkKKyAgICAgICAgc2VsZi5fc29ja2V0LnNlbmRhbGwoYnl0ZXMp
CisKKyAgICBkZWYgZGlzY29ubmVjdChzZWxmKToKKyAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50
TWVkaXVtLmRpc2Nvbm5lY3QoKS4iIiIKKyAgICAgICAgaWYgbm90IHNlbGYuX2Nvbm5lY3RlZDoK
KyAgICAgICAgICAgIHJldHVybgorICAgICAgICBzZWxmLl9zb2NrZXQuY2xvc2UoKQorICAgICAg
ICBzZWxmLl9zb2NrZXQgPSBOb25lCisgICAgICAgIHNlbGYuX2Nvbm5lY3RlZCA9IEZhbHNlCisK
KyAgICBkZWYgX2Vuc3VyZV9jb25uZWN0aW9uKHNlbGYpOgorICAgICAgICAiIiJDb25uZWN0IHRo
aXMgbWVkaXVtIGlmIG5vdCBhbHJlYWR5IGNvbm5lY3RlZC4iIiIKKyAgICAgICAgaWYgc2VsZi5f
Y29ubmVjdGVkOgorICAgICAgICAgICAgcmV0dXJuCisgICAgICAgIHNlbGYuX3NvY2tldCA9IHNv
Y2tldC5zb2NrZXQoKQorICAgICAgICBzZWxmLl9zb2NrZXQuc2V0c29ja29wdChzb2NrZXQuSVBQ
Uk9UT19UQ1AsIHNvY2tldC5UQ1BfTk9ERUxBWSwgMSkKKyAgICAgICAgcmVzdWx0ID0gc2VsZi5f
c29ja2V0LmNvbm5lY3RfZXgoKHNlbGYuX2hvc3QsIGludChzZWxmLl9wb3J0KSkpCisgICAgICAg
IGlmIHJlc3VsdDoKKyAgICAgICAgICAgIHJhaXNlIGVycm9ycy5Db25uZWN0aW9uRXJyb3IoImZh
aWxlZCB0byBjb25uZWN0IHRvICVzOiVkOiAlcyIgJQorICAgICAgICAgICAgICAgICAgICAoc2Vs
Zi5faG9zdCwgc2VsZi5fcG9ydCwgb3Muc3RyZXJyb3IocmVzdWx0KSkpCisgICAgICAgIHNlbGYu
X2Nvbm5lY3RlZCA9IFRydWUKKworICAgIGRlZiBfZmx1c2goc2VsZik6CisgICAgICAgICIiIlNl
ZSBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5fZmx1c2goKS4KKyAgICAgICAgCisgICAgICAgIEZv
ciBUQ1Agd2UgZG8gbm8gZmx1c2hpbmcuIFdlIG1heSB3YW50IHRvIHR1cm4gb2ZmIFRDUF9OT0RF
TEFZIGFuZCAKKyAgICAgICAgYWRkIGEgbWVhbnMgdG8gZG8gYSBmbHVzaCwgYnV0IHRoYXQgY2Fu
IGJlIGRvbmUgaW4gdGhlIGZ1dHVyZS4KKyAgICAgICAgIiIiCisKKyAgICBkZWYgX3JlYWRfYnl0
ZXMoc2VsZiwgY291bnQpOgorICAgICAgICAiIiJTZWUgU21hcnRDbGllbnRNZWRpdW0ucmVhZF9i
eXRlcy4iIiIKKyAgICAgICAgaWYgbm90IHNlbGYuX2Nvbm5lY3RlZDoKKyAgICAgICAgICAgIHJh
aXNlIGVycm9ycy5NZWRpdW1Ob3RDb25uZWN0ZWQoc2VsZikKKyAgICAgICAgcmV0dXJuIHNlbGYu
X3NvY2tldC5yZWN2KGNvdW50KQorCgo=

=== modified file bzrlib/smart/protocol.py // encoding:base64
LS0tIGJ6cmxpYi9zbWFydC9wcm90b2NvbC5weQorKysgYnpybGliL3NtYXJ0L3Byb3RvY29sLnB5
CkBAIC0wLDAgKzEsMzI0IEBACisKKworZnJvbSBjU3RyaW5nSU8gaW1wb3J0IFN0cmluZ0lPCisK
K2Zyb20gYnpybGliIGltcG9ydCBlcnJvcnMKK2Zyb20gYnpybGliLnNtYXJ0IGltcG9ydCByZXF1
ZXN0CisKKworZGVmIF9yZWN2X3R1cGxlKGZyb21fZmlsZSk6CisgICAgcmVxX2xpbmUgPSBmcm9t
X2ZpbGUucmVhZGxpbmUoKQorICAgIHJldHVybiBfZGVjb2RlX3R1cGxlKHJlcV9saW5lKQorCisK
K2RlZiBfZGVjb2RlX3R1cGxlKHJlcV9saW5lKToKKyAgICBpZiByZXFfbGluZSA9PSBOb25lIG9y
IHJlcV9saW5lID09ICcnOgorICAgICAgICByZXR1cm4gTm9uZQorICAgIGlmIHJlcV9saW5lWy0x
XSAhPSAnXG4nOgorICAgICAgICByYWlzZSBlcnJvcnMuU21hcnRQcm90b2NvbEVycm9yKCJyZXF1
ZXN0ICVyIG5vdCB0ZXJtaW5hdGVkIiAlIHJlcV9saW5lKQorICAgIHJldHVybiB0dXBsZShyZXFf
bGluZVs6LTFdLnNwbGl0KCdceDAxJykpCisKKworZGVmIF9lbmNvZGVfdHVwbGUoYXJncyk6Cisg
ICAgIiIiRW5jb2RlIHRoZSB0dXBsZSBhcmdzIHRvIGEgYnl0ZXN0cmVhbS4iIiIKKyAgICByZXR1
cm4gJ1x4MDEnLmpvaW4oYXJncykgKyAnXG4nCisKKworY2xhc3MgU21hcnRQcm90b2NvbEJhc2Uo
b2JqZWN0KToKKyAgICAiIiJNZXRob2RzIGNvbW1vbiB0byBjbGllbnQgYW5kIHNlcnZlciIiIgor
CisgICAgIyBUT0RPOiB0aGlzIG9ubHkgYWN0dWFsbHkgYWNjb21vZGF0ZXMgYSBzaW5nbGUgYmxv
Y2s7IHBvc3NpYmx5IHNob3VsZAorICAgICMgc3VwcG9ydCBtdWx0aXBsZSBjaHVua3M/CisgICAg
ZGVmIF9lbmNvZGVfYnVsa19kYXRhKHNlbGYsIGJvZHkpOgorICAgICAgICAiIiJFbmNvZGUgYm9k
eSBhcyBhIGJ1bGsgZGF0YSBjaHVuay4iIiIKKyAgICAgICAgcmV0dXJuICcnLmpvaW4oKCclZFxu
JyAlIGxlbihib2R5KSwgYm9keSwgJ2RvbmVcbicpKQorCisgICAgZGVmIF9zZXJpYWxpc2Vfb2Zm
c2V0cyhzZWxmLCBvZmZzZXRzKToKKyAgICAgICAgIiIiU2VyaWFsaXNlIGEgcmVhZHYgb2Zmc2V0
IGxpc3QuIiIiCisgICAgICAgIHR4dCA9IFtdCisgICAgICAgIGZvciBzdGFydCwgbGVuZ3RoIGlu
IG9mZnNldHM6CisgICAgICAgICAgICB0eHQuYXBwZW5kKCclZCwlZCcgJSAoc3RhcnQsIGxlbmd0
aCkpCisgICAgICAgIHJldHVybiAnXG4nLmpvaW4odHh0KQorICAgICAgICAKKworY2xhc3MgU21h
cnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoU21hcnRQcm90b2NvbEJhc2UpOgorICAgICIiIlNl
cnZlci1zaWRlIGVuY29kaW5nIGFuZCBkZWNvZGluZyBsb2dpYyBmb3Igc21hcnQgdmVyc2lvbiAx
LiIiIgorICAgIAorICAgIGRlZiBfX2luaXRfXyhzZWxmLCBiYWNraW5nX3RyYW5zcG9ydCwgd3Jp
dGVfZnVuYyk6CisgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0ID0gYmFja2luZ190cmFu
c3BvcnQKKyAgICAgICAgc2VsZi5leGNlc3NfYnVmZmVyID0gJycKKyAgICAgICAgc2VsZi5fZmlu
aXNoZWQgPSBGYWxzZQorICAgICAgICBzZWxmLmluX2J1ZmZlciA9ICcnCisgICAgICAgIHNlbGYu
aGFzX2Rpc3BhdGNoZWQgPSBGYWxzZQorICAgICAgICBzZWxmLnJlcXVlc3QgPSBOb25lCisgICAg
ICAgIHNlbGYuX2JvZHlfZGVjb2RlciA9IE5vbmUKKyAgICAgICAgc2VsZi5fd3JpdGVfZnVuYyA9
IHdyaXRlX2Z1bmMKKworICAgIGRlZiBhY2NlcHRfYnl0ZXMoc2VsZiwgYnl0ZXMpOgorICAgICAg
ICAiIiJUYWtlIGJ5dGVzLCBhbmQgYWR2YW5jZSB0aGUgaW50ZXJuYWwgc3RhdGUgbWFjaGluZSBh
cHByb3ByaWF0ZWx5LgorICAgICAgICAKKyAgICAgICAgOnBhcmFtIGJ5dGVzOiBtdXN0IGJlIGEg
Ynl0ZSBzdHJpbmcKKyAgICAgICAgIiIiCisgICAgICAgIGFzc2VydCBpc2luc3RhbmNlKGJ5dGVz
LCBzdHIpCisgICAgICAgIHNlbGYuaW5fYnVmZmVyICs9IGJ5dGVzCisgICAgICAgIGlmIG5vdCBz
ZWxmLmhhc19kaXNwYXRjaGVkOgorICAgICAgICAgICAgaWYgJ1xuJyBub3QgaW4gc2VsZi5pbl9i
dWZmZXI6CisgICAgICAgICAgICAgICAgIyBubyBjb21tYW5kIGxpbmUgeWV0CisgICAgICAgICAg
ICAgICAgcmV0dXJuCisgICAgICAgICAgICBzZWxmLmhhc19kaXNwYXRjaGVkID0gVHJ1ZQorICAg
ICAgICAgICAgdHJ5OgorICAgICAgICAgICAgICAgIGZpcnN0X2xpbmUsIHNlbGYuaW5fYnVmZmVy
ID0gc2VsZi5pbl9idWZmZXIuc3BsaXQoJ1xuJywgMSkKKyAgICAgICAgICAgICAgICBmaXJzdF9s
aW5lICs9ICdcbicKKyAgICAgICAgICAgICAgICByZXFfYXJncyA9IF9kZWNvZGVfdHVwbGUoZmly
c3RfbGluZSkKKyAgICAgICAgICAgICAgICBzZWxmLnJlcXVlc3QgPSByZXF1ZXN0LlNtYXJ0U2Vy
dmVyUmVxdWVzdEhhbmRsZXIoCisgICAgICAgICAgICAgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJh
bnNwb3J0KQorICAgICAgICAgICAgICAgIHNlbGYucmVxdWVzdC5kaXNwYXRjaF9jb21tYW5kKHJl
cV9hcmdzWzBdLCByZXFfYXJnc1sxOl0pCisgICAgICAgICAgICAgICAgaWYgc2VsZi5yZXF1ZXN0
LmZpbmlzaGVkX3JlYWRpbmc6CisgICAgICAgICAgICAgICAgICAgICMgdHJpdmlhbCByZXF1ZXN0
CisgICAgICAgICAgICAgICAgICAgIHNlbGYuZXhjZXNzX2J1ZmZlciA9IHNlbGYuaW5fYnVmZmVy
CisgICAgICAgICAgICAgICAgICAgIHNlbGYuaW5fYnVmZmVyID0gJycKKyAgICAgICAgICAgICAg
ICAgICAgc2VsZi5fc2VuZF9yZXNwb25zZShzZWxmLnJlcXVlc3QucmVzcG9uc2UuYXJncywKKyAg
ICAgICAgICAgICAgICAgICAgICAgIHNlbGYucmVxdWVzdC5yZXNwb25zZS5ib2R5KQorICAgICAg
ICAgICAgZXhjZXB0IEtleWJvYXJkSW50ZXJydXB0OgorICAgICAgICAgICAgICAgIHJhaXNlCisg
ICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uLCBleGNlcHRpb246CisgICAgICAgICAgICAgICAg
IyBldmVyeXRoaW5nIGVsc2U6IHBhc3MgdG8gY2xpZW50LCBmbHVzaCwgYW5kIHF1aXQKKyAgICAg
ICAgICAgICAgICBzZWxmLl9zZW5kX3Jlc3BvbnNlKCgnZXJyb3InLCBzdHIoZXhjZXB0aW9uKSkp
CisgICAgICAgICAgICAgICAgcmV0dXJuCisKKyAgICAgICAgaWYgc2VsZi5oYXNfZGlzcGF0Y2hl
ZDoKKyAgICAgICAgICAgIGlmIHNlbGYuX2ZpbmlzaGVkOgorICAgICAgICAgICAgICAgICMgbm90
aGluZyB0byBkby5YWFg6IHRoaXMgcm91dGluZSBzaG91bGQgYmUgYSBzaW5nbGUgc3RhdGUgCisg
ICAgICAgICAgICAgICAgIyBtYWNoaW5lIHRvby4KKyAgICAgICAgICAgICAgICBzZWxmLmV4Y2Vz
c19idWZmZXIgKz0gc2VsZi5pbl9idWZmZXIKKyAgICAgICAgICAgICAgICBzZWxmLmluX2J1ZmZl
ciA9ICcnCisgICAgICAgICAgICAgICAgcmV0dXJuCisgICAgICAgICAgICBpZiBzZWxmLl9ib2R5
X2RlY29kZXIgaXMgTm9uZToKKyAgICAgICAgICAgICAgICBzZWxmLl9ib2R5X2RlY29kZXIgPSBM
ZW5ndGhQcmVmaXhlZEJvZHlEZWNvZGVyKCkKKyAgICAgICAgICAgIHNlbGYuX2JvZHlfZGVjb2Rl
ci5hY2NlcHRfYnl0ZXMoc2VsZi5pbl9idWZmZXIpCisgICAgICAgICAgICBzZWxmLmluX2J1ZmZl
ciA9IHNlbGYuX2JvZHlfZGVjb2Rlci51bnVzZWRfZGF0YQorICAgICAgICAgICAgYm9keV9kYXRh
ID0gc2VsZi5fYm9keV9kZWNvZGVyLnJlYWRfcGVuZGluZ19kYXRhKCkKKyAgICAgICAgICAgIHNl
bGYucmVxdWVzdC5hY2NlcHRfYm9keShib2R5X2RhdGEpCisgICAgICAgICAgICBpZiBzZWxmLl9i
b2R5X2RlY29kZXIuZmluaXNoZWRfcmVhZGluZzoKKyAgICAgICAgICAgICAgICBzZWxmLnJlcXVl
c3QuZW5kX29mX2JvZHkoKQorICAgICAgICAgICAgICAgIGFzc2VydCBzZWxmLnJlcXVlc3QuZmlu
aXNoZWRfcmVhZGluZywgXAorICAgICAgICAgICAgICAgICAgICAibm8gbW9yZSBib2R5LCByZXF1
ZXN0IG5vdCBmaW5pc2hlZCIKKyAgICAgICAgICAgIGlmIHNlbGYucmVxdWVzdC5yZXNwb25zZSBp
cyBub3QgTm9uZToKKyAgICAgICAgICAgICAgICBzZWxmLl9zZW5kX3Jlc3BvbnNlKHNlbGYucmVx
dWVzdC5yZXNwb25zZS5hcmdzLAorICAgICAgICAgICAgICAgICAgICBzZWxmLnJlcXVlc3QucmVz
cG9uc2UuYm9keSkKKyAgICAgICAgICAgICAgICBzZWxmLmV4Y2Vzc19idWZmZXIgPSBzZWxmLmlu
X2J1ZmZlcgorICAgICAgICAgICAgICAgIHNlbGYuaW5fYnVmZmVyID0gJycKKyAgICAgICAgICAg
IGVsc2U6CisgICAgICAgICAgICAgICAgYXNzZXJ0IG5vdCBzZWxmLnJlcXVlc3QuZmluaXNoZWRf
cmVhZGluZywgXAorICAgICAgICAgICAgICAgICAgICAibm8gcmVzcG9uc2UgYW5kIHdlIGhhdmUg
ZmluaXNoZWQgcmVhZGluZy4iCisKKyAgICBkZWYgX3NlbmRfcmVzcG9uc2Uoc2VsZiwgYXJncywg
Ym9keT1Ob25lKToKKyAgICAgICAgIiIiU2VuZCBhIHNtYXJ0IHNlcnZlciByZXNwb25zZSBkb3du
IHRoZSBvdXRwdXQgc3RyZWFtLiIiIgorICAgICAgICBhc3NlcnQgbm90IHNlbGYuX2ZpbmlzaGVk
LCAncmVzcG9uc2UgYWxyZWFkeSBzZW50JworICAgICAgICBzZWxmLl9maW5pc2hlZCA9IFRydWUK
KyAgICAgICAgc2VsZi5fd3JpdGVfZnVuYyhfZW5jb2RlX3R1cGxlKGFyZ3MpKQorICAgICAgICBp
ZiBib2R5IGlzIG5vdCBOb25lOgorICAgICAgICAgICAgYXNzZXJ0IGlzaW5zdGFuY2UoYm9keSwg
c3RyKSwgJ2JvZHkgbXVzdCBiZSBhIHN0cicKKyAgICAgICAgICAgIGJ5dGVzID0gc2VsZi5fZW5j
b2RlX2J1bGtfZGF0YShib2R5KQorICAgICAgICAgICAgc2VsZi5fd3JpdGVfZnVuYyhieXRlcykK
KworICAgIGRlZiBuZXh0X3JlYWRfc2l6ZShzZWxmKToKKyAgICAgICAgaWYgc2VsZi5fZmluaXNo
ZWQ6CisgICAgICAgICAgICByZXR1cm4gMAorICAgICAgICBpZiBzZWxmLl9ib2R5X2RlY29kZXIg
aXMgTm9uZToKKyAgICAgICAgICAgIHJldHVybiAxCisgICAgICAgIGVsc2U6CisgICAgICAgICAg
ICByZXR1cm4gc2VsZi5fYm9keV9kZWNvZGVyLm5leHRfcmVhZF9zaXplKCkKKworCitjbGFzcyBM
ZW5ndGhQcmVmaXhlZEJvZHlEZWNvZGVyKG9iamVjdCk6CisgICAgIiIiRGVjb2RlcyB0aGUgbGVu
Z3RoLXByZWZpeGVkIGJ1bGsgZGF0YS4iIiIKKyAgICAKKyAgICBkZWYgX19pbml0X18oc2VsZik6
CisgICAgICAgIHNlbGYuYnl0ZXNfbGVmdCA9IE5vbmUKKyAgICAgICAgc2VsZi5maW5pc2hlZF9y
ZWFkaW5nID0gRmFsc2UKKyAgICAgICAgc2VsZi51bnVzZWRfZGF0YSA9ICcnCisgICAgICAgIHNl
bGYuc3RhdGVfYWNjZXB0ID0gc2VsZi5fc3RhdGVfYWNjZXB0X2V4cGVjdGluZ19sZW5ndGgKKyAg
ICAgICAgc2VsZi5zdGF0ZV9yZWFkID0gc2VsZi5fc3RhdGVfcmVhZF9ub19kYXRhCisgICAgICAg
IHNlbGYuX2luX2J1ZmZlciA9ICcnCisgICAgICAgIHNlbGYuX3RyYWlsZXJfYnVmZmVyID0gJycK
KyAgICAKKyAgICBkZWYgYWNjZXB0X2J5dGVzKHNlbGYsIGJ5dGVzKToKKyAgICAgICAgIiIiRGVj
b2RlIGFzIG11Y2ggb2YgYnl0ZXMgYXMgcG9zc2libGUuCisKKyAgICAgICAgSWYgJ2J5dGVzJyBj
b250YWlucyB0b28gbXVjaCBkYXRhIGl0IHdpbGwgYmUgYXBwZW5kZWQgdG8KKyAgICAgICAgc2Vs
Zi51bnVzZWRfZGF0YS4KKworICAgICAgICBmaW5pc2hlZF9yZWFkaW5nIHdpbGwgYmUgc2V0IHdo
ZW4gbm8gbW9yZSBkYXRhIGlzIHJlcXVpcmVkLiAgRnVydGhlcgorICAgICAgICBkYXRhIHdpbGwg
YmUgYXBwZW5kZWQgdG8gc2VsZi51bnVzZWRfZGF0YS4KKyAgICAgICAgIiIiCisgICAgICAgICMg
YWNjZXB0X2J5dGVzIGlzIGFsbG93ZWQgdG8gY2hhbmdlIHRoZSBzdGF0ZQorICAgICAgICBjdXJy
ZW50X3N0YXRlID0gc2VsZi5zdGF0ZV9hY2NlcHQKKyAgICAgICAgc2VsZi5zdGF0ZV9hY2NlcHQo
Ynl0ZXMpCisgICAgICAgIHdoaWxlIGN1cnJlbnRfc3RhdGUgIT0gc2VsZi5zdGF0ZV9hY2NlcHQ6
CisgICAgICAgICAgICBjdXJyZW50X3N0YXRlID0gc2VsZi5zdGF0ZV9hY2NlcHQKKyAgICAgICAg
ICAgIHNlbGYuc3RhdGVfYWNjZXB0KCcnKQorCisgICAgZGVmIG5leHRfcmVhZF9zaXplKHNlbGYp
OgorICAgICAgICBpZiBzZWxmLmJ5dGVzX2xlZnQgaXMgbm90IE5vbmU6CisgICAgICAgICAgICAj
IElkZWFsbHkgd2Ugd2FudCB0byByZWFkIGFsbCB0aGUgcmVtYWluZGVyIG9mIHRoZSBib2R5IGFu
ZCB0aGUKKyAgICAgICAgICAgICMgdHJhaWxlciBpbiBvbmUgZ28uCisgICAgICAgICAgICByZXR1
cm4gc2VsZi5ieXRlc19sZWZ0ICsgNQorICAgICAgICBlbGlmIHNlbGYuc3RhdGVfYWNjZXB0ID09
IHNlbGYuX3N0YXRlX2FjY2VwdF9yZWFkaW5nX3RyYWlsZXI6CisgICAgICAgICAgICAjIEp1c3Qg
dGhlIHRyYWlsZXIgbGVmdAorICAgICAgICAgICAgcmV0dXJuIDUgLSBsZW4oc2VsZi5fdHJhaWxl
cl9idWZmZXIpCisgICAgICAgIGVsaWYgc2VsZi5zdGF0ZV9hY2NlcHQgPT0gc2VsZi5fc3RhdGVf
YWNjZXB0X2V4cGVjdGluZ19sZW5ndGg6CisgICAgICAgICAgICAjIFRoZXJlJ3Mgc3RpbGwgYXQg
bGVhc3QgNiBieXRlcyBsZWZ0ICgnXG4nIHRvIGVuZCB0aGUgbGVuZ3RoLCBwbHVzCisgICAgICAg
ICAgICAjICdkb25lXG4nKS4KKyAgICAgICAgICAgIHJldHVybiA2CisgICAgICAgIGVsc2U6Cisg
ICAgICAgICAgICAjIFJlYWRpbmcgZXhjZXNzIGRhdGEuICBFaXRoZXIgd2F5LCAxIGJ5dGUgYXQg
YSB0aW1lIGlzIGZpbmUuCisgICAgICAgICAgICByZXR1cm4gMQorICAgICAgICAKKyAgICBkZWYg
cmVhZF9wZW5kaW5nX2RhdGEoc2VsZik6CisgICAgICAgICIiIlJldHVybiBhbnkgcGVuZGluZyBk
YXRhIHRoYXQgaGFzIGJlZW4gZGVjb2RlZC4iIiIKKyAgICAgICAgcmV0dXJuIHNlbGYuc3RhdGVf
cmVhZCgpCisKKyAgICBkZWYgX3N0YXRlX2FjY2VwdF9leHBlY3RpbmdfbGVuZ3RoKHNlbGYsIGJ5
dGVzKToKKyAgICAgICAgc2VsZi5faW5fYnVmZmVyICs9IGJ5dGVzCisgICAgICAgIHBvcyA9IHNl
bGYuX2luX2J1ZmZlci5maW5kKCdcbicpCisgICAgICAgIGlmIHBvcyA9PSAtMToKKyAgICAgICAg
ICAgIHJldHVybgorICAgICAgICBzZWxmLmJ5dGVzX2xlZnQgPSBpbnQoc2VsZi5faW5fYnVmZmVy
Wzpwb3NdKQorICAgICAgICBzZWxmLl9pbl9idWZmZXIgPSBzZWxmLl9pbl9idWZmZXJbcG9zKzE6
XQorICAgICAgICBzZWxmLmJ5dGVzX2xlZnQgLT0gbGVuKHNlbGYuX2luX2J1ZmZlcikKKyAgICAg
ICAgc2VsZi5zdGF0ZV9hY2NlcHQgPSBzZWxmLl9zdGF0ZV9hY2NlcHRfcmVhZGluZ19ib2R5Cisg
ICAgICAgIHNlbGYuc3RhdGVfcmVhZCA9IHNlbGYuX3N0YXRlX3JlYWRfaW5fYnVmZmVyCisKKyAg
ICBkZWYgX3N0YXRlX2FjY2VwdF9yZWFkaW5nX2JvZHkoc2VsZiwgYnl0ZXMpOgorICAgICAgICBz
ZWxmLl9pbl9idWZmZXIgKz0gYnl0ZXMKKyAgICAgICAgc2VsZi5ieXRlc19sZWZ0IC09IGxlbihi
eXRlcykKKyAgICAgICAgaWYgc2VsZi5ieXRlc19sZWZ0IDw9IDA6CisgICAgICAgICAgICAjIEZp
bmlzaGVkIHdpdGggYm9keQorICAgICAgICAgICAgaWYgc2VsZi5ieXRlc19sZWZ0ICE9IDA6Cisg
ICAgICAgICAgICAgICAgc2VsZi5fdHJhaWxlcl9idWZmZXIgPSBzZWxmLl9pbl9idWZmZXJbc2Vs
Zi5ieXRlc19sZWZ0Ol0KKyAgICAgICAgICAgICAgICBzZWxmLl9pbl9idWZmZXIgPSBzZWxmLl9p
bl9idWZmZXJbOnNlbGYuYnl0ZXNfbGVmdF0KKyAgICAgICAgICAgIHNlbGYuYnl0ZXNfbGVmdCA9
IE5vbmUKKyAgICAgICAgICAgIHNlbGYuc3RhdGVfYWNjZXB0ID0gc2VsZi5fc3RhdGVfYWNjZXB0
X3JlYWRpbmdfdHJhaWxlcgorICAgICAgICAKKyAgICBkZWYgX3N0YXRlX2FjY2VwdF9yZWFkaW5n
X3RyYWlsZXIoc2VsZiwgYnl0ZXMpOgorICAgICAgICBzZWxmLl90cmFpbGVyX2J1ZmZlciArPSBi
eXRlcworICAgICAgICAjIFRPRE86IHdoYXQgaWYgdGhlIHRyYWlsZXIgZG9lcyBub3QgbWF0Y2gg
ImRvbmVcbiI/ICBTaG91bGQgdGhpcyByYWlzZQorICAgICAgICAjIGEgUHJvdG9jb2xWaW9sYXRp
b24gZXhjZXB0aW9uPworICAgICAgICBpZiBzZWxmLl90cmFpbGVyX2J1ZmZlci5zdGFydHN3aXRo
KCdkb25lXG4nKToKKyAgICAgICAgICAgIHNlbGYudW51c2VkX2RhdGEgPSBzZWxmLl90cmFpbGVy
X2J1ZmZlcltsZW4oJ2RvbmVcbicpOl0KKyAgICAgICAgICAgIHNlbGYuc3RhdGVfYWNjZXB0ID0g
c2VsZi5fc3RhdGVfYWNjZXB0X3JlYWRpbmdfdW51c2VkCisgICAgICAgICAgICBzZWxmLmZpbmlz
aGVkX3JlYWRpbmcgPSBUcnVlCisgICAgCisgICAgZGVmIF9zdGF0ZV9hY2NlcHRfcmVhZGluZ191
bnVzZWQoc2VsZiwgYnl0ZXMpOgorICAgICAgICBzZWxmLnVudXNlZF9kYXRhICs9IGJ5dGVzCisK
KyAgICBkZWYgX3N0YXRlX3JlYWRfbm9fZGF0YShzZWxmKToKKyAgICAgICAgcmV0dXJuICcnCisK
KyAgICBkZWYgX3N0YXRlX3JlYWRfaW5fYnVmZmVyKHNlbGYpOgorICAgICAgICByZXN1bHQgPSBz
ZWxmLl9pbl9idWZmZXIKKyAgICAgICAgc2VsZi5faW5fYnVmZmVyID0gJycKKyAgICAgICAgcmV0
dXJuIHJlc3VsdAorCisKK2NsYXNzIFNtYXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKFNtYXJ0
UHJvdG9jb2xCYXNlKToKKyAgICAiIiJUaGUgY2xpZW50LXNpZGUgcHJvdG9jb2wgZm9yIHNtYXJ0
IHZlcnNpb24gMS4iIiIKKworICAgIGRlZiBfX2luaXRfXyhzZWxmLCByZXF1ZXN0KToKKyAgICAg
ICAgIiIiQ29uc3RydWN0IGEgU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9jb2xPbmUuCisKKyAgICAg
ICAgOnBhcmFtIHJlcXVlc3Q6IEEgU21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0IHRvIHNlcmlhbGlz
ZSBvbnRvIGFuZAorICAgICAgICAgICAgZGVzZXJpYWxpc2UgZnJvbS4KKyAgICAgICAgIiIiCisg
ICAgICAgIHNlbGYuX3JlcXVlc3QgPSByZXF1ZXN0CisgICAgICAgIHNlbGYuX2JvZHlfYnVmZmVy
ID0gTm9uZQorCisgICAgZGVmIGNhbGwoc2VsZiwgKmFyZ3MpOgorICAgICAgICBieXRlcyA9IF9l
bmNvZGVfdHVwbGUoYXJncykKKyAgICAgICAgc2VsZi5fcmVxdWVzdC5hY2NlcHRfYnl0ZXMoYnl0
ZXMpCisgICAgICAgIHNlbGYuX3JlcXVlc3QuZmluaXNoZWRfd3JpdGluZygpCisKKyAgICBkZWYg
Y2FsbF93aXRoX2JvZHlfYnl0ZXMoc2VsZiwgYXJncywgYm9keSk6CisgICAgICAgICIiIk1ha2Ug
YSByZW1vdGUgY2FsbCBvZiBhcmdzIHdpdGggYm9keSBieXRlcyAnYm9keScuCisKKyAgICAgICAg
QWZ0ZXIgY2FsbGluZyB0aGlzLCBjYWxsIHJlYWRfcmVzcG9uc2VfdHVwbGUgdG8gZmluZCB0aGUg
cmVzdWx0IG91dC4KKyAgICAgICAgIiIiCisgICAgICAgIGJ5dGVzID0gX2VuY29kZV90dXBsZShh
cmdzKQorICAgICAgICBzZWxmLl9yZXF1ZXN0LmFjY2VwdF9ieXRlcyhieXRlcykKKyAgICAgICAg
Ynl0ZXMgPSBzZWxmLl9lbmNvZGVfYnVsa19kYXRhKGJvZHkpCisgICAgICAgIHNlbGYuX3JlcXVl
c3QuYWNjZXB0X2J5dGVzKGJ5dGVzKQorICAgICAgICBzZWxmLl9yZXF1ZXN0LmZpbmlzaGVkX3dy
aXRpbmcoKQorCisgICAgZGVmIGNhbGxfd2l0aF9ib2R5X3JlYWR2X2FycmF5KHNlbGYsIGFyZ3Ms
IGJvZHkpOgorICAgICAgICAiIiJNYWtlIGEgcmVtb3RlIGNhbGwgd2l0aCBhIHJlYWR2IGFycmF5
LgorCisgICAgICAgIFRoZSBib2R5IGlzIGVuY29kZWQgd2l0aCBvbmUgbGluZSBwZXIgcmVhZHYg
b2Zmc2V0IHBhaXIuIFRoZSBudW1iZXJzIGluCisgICAgICAgIGVhY2ggcGFpciBhcmUgc2VwYXJh
dGVkIGJ5IGEgY29tbWEsIGFuZCBubyB0cmFpbGluZyBcbiBpcyBlbWl0dGVkLgorICAgICAgICAi
IiIKKyAgICAgICAgYnl0ZXMgPSBfZW5jb2RlX3R1cGxlKGFyZ3MpCisgICAgICAgIHNlbGYuX3Jl
cXVlc3QuYWNjZXB0X2J5dGVzKGJ5dGVzKQorICAgICAgICByZWFkdl9ieXRlcyA9IHNlbGYuX3Nl
cmlhbGlzZV9vZmZzZXRzKGJvZHkpCisgICAgICAgIGJ5dGVzID0gc2VsZi5fZW5jb2RlX2J1bGtf
ZGF0YShyZWFkdl9ieXRlcykKKyAgICAgICAgc2VsZi5fcmVxdWVzdC5hY2NlcHRfYnl0ZXMoYnl0
ZXMpCisgICAgICAgIHNlbGYuX3JlcXVlc3QuZmluaXNoZWRfd3JpdGluZygpCisKKyAgICBkZWYg
Y2FuY2VsX3JlYWRfYm9keShzZWxmKToKKyAgICAgICAgIiIiQWZ0ZXIgZXhwZWN0aW5nIGEgYm9k
eSwgYSByZXNwb25zZSBjb2RlIG1heSBpbmRpY2F0ZSBvbmUgb3RoZXJ3aXNlLgorCisgICAgICAg
IFRoaXMgbWV0aG9kIGxldHMgdGhlIGRvbWFpbiBjbGllbnQgaW5mb3JtIHRoZSBwcm90b2NvbCB0
aGF0IG5vIGJvZHkKKyAgICAgICAgd2lsbCBiZSB0cmFuc21pdHRlZC4gVGhpcyBpcyBhIHRlcm1p
bmFsIG1ldGhvZDogYWZ0ZXIgY2FsbGluZyBpdCB0aGUKKyAgICAgICAgcHJvdG9jb2wgaXMgbm90
IGFibGUgdG8gYmUgdXNlZCBmdXJ0aGVyLgorICAgICAgICAiIiIKKyAgICAgICAgc2VsZi5fcmVx
dWVzdC5maW5pc2hlZF9yZWFkaW5nKCkKKworICAgIGRlZiByZWFkX3Jlc3BvbnNlX3R1cGxlKHNl
bGYsIGV4cGVjdF9ib2R5PUZhbHNlKToKKyAgICAgICAgIiIiUmVhZCBhIHJlc3BvbnNlIHR1cGxl
IGZyb20gdGhlIHdpcmUuCisKKyAgICAgICAgVGhpcyBzaG91bGQgb25seSBiZSBjYWxsZWQgb25j
ZS4KKyAgICAgICAgIiIiCisgICAgICAgIHJlc3VsdCA9IHNlbGYuX3JlY3ZfdHVwbGUoKQorICAg
ICAgICBpZiBub3QgZXhwZWN0X2JvZHk6CisgICAgICAgICAgICBzZWxmLl9yZXF1ZXN0LmZpbmlz
aGVkX3JlYWRpbmcoKQorICAgICAgICByZXR1cm4gcmVzdWx0CisKKyAgICBkZWYgcmVhZF9ib2R5
X2J5dGVzKHNlbGYsIGNvdW50PS0xKToKKyAgICAgICAgIiIiUmVhZCBieXRlcyBmcm9tIHRoZSBi
b2R5LCBkZWNvZGluZyBpbnRvIGEgYnl0ZSBzdHJlYW0uCisgICAgICAgIAorICAgICAgICBXZSBy
ZWFkIGFsbCBieXRlcyBhdCBvbmNlIHRvIGVuc3VyZSB3ZSd2ZSBjaGVja2VkIHRoZSB0cmFpbGVy
IGZvciAKKyAgICAgICAgZXJyb3JzLCBhbmQgdGhlbiBmZWVkIHRoZSBidWZmZXIgYmFjayBhcyBy
ZWFkX2JvZHlfYnl0ZXMgaXMgY2FsbGVkLgorICAgICAgICAiIiIKKyAgICAgICAgaWYgc2VsZi5f
Ym9keV9idWZmZXIgaXMgbm90IE5vbmU6CisgICAgICAgICAgICByZXR1cm4gc2VsZi5fYm9keV9i
dWZmZXIucmVhZChjb3VudCkKKyAgICAgICAgX2JvZHlfZGVjb2RlciA9IExlbmd0aFByZWZpeGVk
Qm9keURlY29kZXIoKQorCisgICAgICAgIHdoaWxlIG5vdCBfYm9keV9kZWNvZGVyLmZpbmlzaGVk
X3JlYWRpbmc6CisgICAgICAgICAgICBieXRlc193YW50ZWQgPSBfYm9keV9kZWNvZGVyLm5leHRf
cmVhZF9zaXplKCkKKyAgICAgICAgICAgIGJ5dGVzID0gc2VsZi5fcmVxdWVzdC5yZWFkX2J5dGVz
KGJ5dGVzX3dhbnRlZCkKKyAgICAgICAgICAgIF9ib2R5X2RlY29kZXIuYWNjZXB0X2J5dGVzKGJ5
dGVzKQorICAgICAgICBzZWxmLl9yZXF1ZXN0LmZpbmlzaGVkX3JlYWRpbmcoKQorICAgICAgICBz
ZWxmLl9ib2R5X2J1ZmZlciA9IFN0cmluZ0lPKF9ib2R5X2RlY29kZXIucmVhZF9wZW5kaW5nX2Rh
dGEoKSkKKyAgICAgICAgIyBYWFg6IFRPRE8gY2hlY2sgdGhlIHRyYWlsZXIgcmVzdWx0LgorICAg
ICAgICByZXR1cm4gc2VsZi5fYm9keV9idWZmZXIucmVhZChjb3VudCkKKworICAgIGRlZiBfcmVj
dl90dXBsZShzZWxmKToKKyAgICAgICAgIiIiUmVjZWl2ZSBhIHR1cGxlIGZyb20gdGhlIG1lZGl1
bSByZXF1ZXN0LiIiIgorICAgICAgICBsaW5lID0gJycKKyAgICAgICAgd2hpbGUgbm90IGxpbmUg
b3IgbGluZVstMV0gIT0gJ1xuJzoKKyAgICAgICAgICAgICMgVE9ETzogdGhpcyBpcyBpbmVmZmlj
aWVudCAtIGJ1dCB0dXBsZXMgYXJlIHNob3J0LgorICAgICAgICAgICAgbmV3X2NoYXIgPSBzZWxm
Ll9yZXF1ZXN0LnJlYWRfYnl0ZXMoMSkKKyAgICAgICAgICAgIGxpbmUgKz0gbmV3X2NoYXIKKyAg
ICAgICAgICAgIGFzc2VydCBuZXdfY2hhciAhPSAnJywgImVuZCBvZiBmaWxlIHJlYWRpbmcgZnJv
bSBzZXJ2ZXIuIgorICAgICAgICByZXR1cm4gX2RlY29kZV90dXBsZShsaW5lKQorCisgICAgZGVm
IHF1ZXJ5X3ZlcnNpb24oc2VsZik6CisgICAgICAgICIiIlJldHVybiBwcm90b2NvbCB2ZXJzaW9u
IG51bWJlciBvZiB0aGUgc2VydmVyLiIiIgorICAgICAgICBzZWxmLmNhbGwoJ2hlbGxvJykKKyAg
ICAgICAgcmVzcCA9IHNlbGYucmVhZF9yZXNwb25zZV90dXBsZSgpCisgICAgICAgIGlmIHJlc3Ag
PT0gKCdvaycsICcxJyk6CisgICAgICAgICAgICByZXR1cm4gMQorICAgICAgICBlbHNlOgorICAg
ICAgICAgICAgcmFpc2UgZXJyb3JzLlNtYXJ0UHJvdG9jb2xFcnJvcigiYmFkIHJlc3BvbnNlICVy
IiAlIChyZXNwLCkpCisKKworCgo=

=== modified file bzrlib/smart/request.py // encoding:base64
LS0tIGJ6cmxpYi9zbWFydC9yZXF1ZXN0LnB5CisrKyBienJsaWIvc21hcnQvcmVxdWVzdC5weQpA
QCAtMCwwICsxLDI0OSBAQAorCitpbXBvcnQgdGVtcGZpbGUKKworZnJvbSBienJsaWIgaW1wb3J0
ICgKKyAgICBienJkaXIsCisgICAgZXJyb3JzLAorICAgIHJldmlzaW9uCisgICAgKQorZnJvbSBi
enJsaWIuYnVuZGxlLnNlcmlhbGl6ZXIgaW1wb3J0IHdyaXRlX2J1bmRsZQorCisKK2NsYXNzIFNt
YXJ0U2VydmVyUmVzcG9uc2Uob2JqZWN0KToKKyAgICAiIiJSZXNwb25zZSBnZW5lcmF0ZWQgYnkg
U21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlci4iIiIKKworICAgIGRlZiBfX2luaXRfXyhzZWxmLCBh
cmdzLCBib2R5PU5vbmUpOgorICAgICAgICBzZWxmLmFyZ3MgPSBhcmdzCisgICAgICAgIHNlbGYu
Ym9keSA9IGJvZHkKKworIyBYWFg6IFRPRE86IENyZWF0ZSBhIFNtYXJ0U2VydmVyUmVxdWVzdEhh
bmRsZXIgd2hpY2ggd2lsbCB0YWtlIHRoZSByZXNwb25zaWJpbGl0eQorIyBmb3IgZGVsaXZlcmlu
ZyB0aGUgZGF0YSBmb3IgYSByZXF1ZXN0LiBUaGlzIGNvdWxkIGJlIGRvbmUgd2l0aCBhcyB0aGUK
KyMgU3RyZWFtU2VydmVyLCB0aG91Z2ggdGhhdCB3b3VsZCBjcmVhdGUgY29uZmxhdGlvbiBiZXR3
ZWVuIHJlcXVlc3QgYW5kIHJlc3BvbnNlCisjIHdoaWNoIG1heSBiZSB1bmRlc2lyYWJsZS4KKwor
Y2xhc3MgU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihvYmplY3QpOgorICAgICIiIlByb3RvY29s
IGxvZ2ljIGZvciBzbWFydCBzZXJ2ZXIuCisgICAgCisgICAgVGhpcyBkb2Vzbid0IGhhbmRsZSBz
ZXJpYWxpemF0aW9uIGF0IGFsbCwgaXQganVzdCBwcm9jZXNzZXMgcmVxdWVzdHMgYW5kCisgICAg
Y3JlYXRlcyByZXNwb25zZXMuCisgICAgIiIiCisKKyAgICAjIElNUE9SVEFOVCBGT1IgSU1QTEVN
RU5UT1JTOiBJdCBpcyBpbXBvcnRhbnQgdGhhdCBTbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyCisg
ICAgIyBub3QgY29udGFpbiBlbmNvZGluZyBvciBkZWNvZGluZyBsb2dpYyB0byBhbGxvdyB0aGUg
d2lyZSBwcm90b2NvbCB0byB2YXJ5CisgICAgIyBmcm9tIHRoZSBvYmplY3QgcHJvdG9jb2w6IHdl
IHdpbGwgd2FudCB0byB0d2VhayB0aGUgd2lyZSBwcm90b2NvbCBzZXBhcmF0ZQorICAgICMgZnJv
bSB0aGUgb2JqZWN0IG1vZGVsLCBhbmQgaWRlYWxseSB3ZSB3aWxsIGJlIGFibGUgdG8gZG8gdGhh
dCB3aXRob3V0CisgICAgIyBoYXZpbmcgYSBTbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyIHN1YmNs
YXNzIGZvciBlYWNoIHdpcmUgcHJvdG9jb2wsIHJhdGhlcgorICAgICMganVzdCBhIFByb3RvY29s
IHN1YmNsYXNzLgorCisgICAgIyBUT0RPOiBCZXR0ZXIgd2F5IG9mIHJlcHJlc2VudGluZyB0aGUg
Ym9keSBmb3IgY29tbWFuZHMgdGhhdCB0YWtlIGl0LAorICAgICMgYW5kIGFsbG93IGl0IHRvIGJl
IHN0cmVhbWVkIGludG8gdGhlIHNlcnZlci4KKyAgICAKKyAgICBkZWYgX19pbml0X18oc2VsZiwg
YmFja2luZ190cmFuc3BvcnQpOgorICAgICAgICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydCA9IGJh
Y2tpbmdfdHJhbnNwb3J0CisgICAgICAgIHNlbGYuX2NvbnZlcnRlZF9jb21tYW5kID0gRmFsc2UK
KyAgICAgICAgc2VsZi5maW5pc2hlZF9yZWFkaW5nID0gRmFsc2UKKyAgICAgICAgc2VsZi5fYm9k
eV9ieXRlcyA9ICcnCisgICAgICAgIHNlbGYucmVzcG9uc2UgPSBOb25lCisKKyAgICBkZWYgYWNj
ZXB0X2JvZHkoc2VsZiwgYnl0ZXMpOgorICAgICAgICAiIiJBY2NlcHQgYm9keSBkYXRhLgorCisg
ICAgICAgIFRoaXMgc2hvdWxkIGJlIG92ZXJyaWRlbiBmb3IgZWFjaCBjb21tYW5kIHRoYXQgZGVz
aXJlZCBib2R5IGRhdGEgdG8KKyAgICAgICAgaGFuZGxlIHRoZSByaWdodCBmb3JtYXQgb2YgdGhh
dCBkYXRhLiBJLmUuIHBsYWluIGJ5dGVzLCBhIGJ1bmRsZSBldGMuCisKKyAgICAgICAgVGhlIGRl
c2VyaWFsaXNhdGlvbiBpbnRvIHRoYXQgZm9ybWF0IHNob3VsZCBiZSBkb25lIGluIHRoZSBQcm90
b2NvbAorICAgICAgICBvYmplY3QuIFNldCBzZWxmLmRlc2lyZWRfYm9keV9mb3JtYXQgdG8gdGhl
IGZvcm1hdCB5b3VyIG1ldGhvZCB3aWxsCisgICAgICAgIGhhbmRsZS4KKyAgICAgICAgIiIiCisg
ICAgICAgICMgZGVmYXVsdCBmYWxsYmFjayBpcyB0byBhY2N1bXVsYXRlIGJ5dGVzLgorICAgICAg
ICBzZWxmLl9ib2R5X2J5dGVzICs9IGJ5dGVzCisgICAgICAgIAorICAgIGRlZiBfZW5kX29mX2Jv
ZHlfaGFuZGxlcihzZWxmKToKKyAgICAgICAgIiIiQW4gdW5pbXBsZW1lbnRlZCBlbmQgb2YgYm9k
eSBoYW5kbGVyLiIiIgorICAgICAgICByYWlzZSBOb3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuX2Vu
ZF9vZl9ib2R5X2hhbmRsZXIpCisgICAgICAgIAorICAgIGRlZiBkb19oZWxsbyhzZWxmKToKKyAg
ICAgICAgIiIiQW5zd2VyIGEgdmVyc2lvbiByZXF1ZXN0IHdpdGggbXkgdmVyc2lvbi4iIiIKKyAg
ICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVzcG9uc2UoKCdvaycsICcxJykpCisKKyAgICBkZWYg
ZG9faGFzKHNlbGYsIHJlbHBhdGgpOgorICAgICAgICByID0gc2VsZi5fYmFja2luZ190cmFuc3Bv
cnQuaGFzKHJlbHBhdGgpIGFuZCAneWVzJyBvciAnbm8nCisgICAgICAgIHJldHVybiBTbWFydFNl
cnZlclJlc3BvbnNlKChyLCkpCisKKyAgICBkZWYgZG9fZ2V0KHNlbGYsIHJlbHBhdGgpOgorICAg
ICAgICBiYWNraW5nX2J5dGVzID0gc2VsZi5fYmFja2luZ190cmFuc3BvcnQuZ2V0X2J5dGVzKHJl
bHBhdGgpCisgICAgICAgIHJldHVybiBTbWFydFNlcnZlclJlc3BvbnNlKCgnb2snLCksIGJhY2tp
bmdfYnl0ZXMpCisKKyAgICBkZWYgX2Rlc2VyaWFsaXNlX29wdGlvbmFsX21vZGUoc2VsZiwgbW9k
ZSk6CisgICAgICAgICMgWFhYOiBGSVhNRSB0aGlzIHNob3VsZCBiZSBvbiB0aGUgcHJvdG9jb2wg
b2JqZWN0LgorICAgICAgICBpZiBtb2RlID09ICcnOgorICAgICAgICAgICAgcmV0dXJuIE5vbmUK
KyAgICAgICAgZWxzZToKKyAgICAgICAgICAgIHJldHVybiBpbnQobW9kZSkKKworICAgIGRlZiBk
b19hcHBlbmQoc2VsZiwgcmVscGF0aCwgbW9kZSk6CisgICAgICAgIHNlbGYuX2NvbnZlcnRlZF9j
b21tYW5kID0gVHJ1ZQorICAgICAgICBzZWxmLl9yZWxwYXRoID0gcmVscGF0aAorICAgICAgICBz
ZWxmLl9tb2RlID0gc2VsZi5fZGVzZXJpYWxpc2Vfb3B0aW9uYWxfbW9kZShtb2RlKQorICAgICAg
ICBzZWxmLl9lbmRfb2ZfYm9keV9oYW5kbGVyID0gc2VsZi5faGFuZGxlX2RvX2FwcGVuZF9lbmQK
KyAgICAKKyAgICBkZWYgX2hhbmRsZV9kb19hcHBlbmRfZW5kKHNlbGYpOgorICAgICAgICBvbGRf
bGVuZ3RoID0gc2VsZi5fYmFja2luZ190cmFuc3BvcnQuYXBwZW5kX2J5dGVzKAorICAgICAgICAg
ICAgc2VsZi5fcmVscGF0aCwgc2VsZi5fYm9keV9ieXRlcywgc2VsZi5fbW9kZSkKKyAgICAgICAg
c2VsZi5yZXNwb25zZSA9IFNtYXJ0U2VydmVyUmVzcG9uc2UoKCdhcHBlbmRlZCcsICclZCcgJSBv
bGRfbGVuZ3RoKSkKKworICAgIGRlZiBkb19kZWxldGUoc2VsZiwgcmVscGF0aCk6CisgICAgICAg
IHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LmRlbGV0ZShyZWxwYXRoKQorCisgICAgZGVmIGRvX2l0
ZXJfZmlsZXNfcmVjdXJzaXZlKHNlbGYsIHJlbHBhdGgpOgorICAgICAgICB0cmFuc3BvcnQgPSBz
ZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5jbG9uZShyZWxwYXRoKQorICAgICAgICBmaWxlbmFtZXMg
PSB0cmFuc3BvcnQuaXRlcl9maWxlc19yZWN1cnNpdmUoKQorICAgICAgICByZXR1cm4gU21hcnRT
ZXJ2ZXJSZXNwb25zZSgoJ25hbWVzJywpICsgdHVwbGUoZmlsZW5hbWVzKSkKKworICAgIGRlZiBk
b19saXN0X2RpcihzZWxmLCByZWxwYXRoKToKKyAgICAgICAgZmlsZW5hbWVzID0gc2VsZi5fYmFj
a2luZ190cmFuc3BvcnQubGlzdF9kaXIocmVscGF0aCkKKyAgICAgICAgcmV0dXJuIFNtYXJ0U2Vy
dmVyUmVzcG9uc2UoKCduYW1lcycsKSArIHR1cGxlKGZpbGVuYW1lcykpCisKKyAgICBkZWYgZG9f
bWtkaXIoc2VsZiwgcmVscGF0aCwgbW9kZSk6CisgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNw
b3J0Lm1rZGlyKHJlbHBhdGgsCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IHNlbGYuX2Rlc2VyaWFsaXNlX29wdGlvbmFsX21vZGUobW9kZSkpCisKKyAgICBkZWYgZG9fbW92
ZShzZWxmLCByZWxfZnJvbSwgcmVsX3RvKToKKyAgICAgICAgc2VsZi5fYmFja2luZ190cmFuc3Bv
cnQubW92ZShyZWxfZnJvbSwgcmVsX3RvKQorCisgICAgZGVmIGRvX3B1dChzZWxmLCByZWxwYXRo
LCBtb2RlKToKKyAgICAgICAgc2VsZi5fY29udmVydGVkX2NvbW1hbmQgPSBUcnVlCisgICAgICAg
IHNlbGYuX3JlbHBhdGggPSByZWxwYXRoCisgICAgICAgIHNlbGYuX21vZGUgPSBzZWxmLl9kZXNl
cmlhbGlzZV9vcHRpb25hbF9tb2RlKG1vZGUpCisgICAgICAgIHNlbGYuX2VuZF9vZl9ib2R5X2hh
bmRsZXIgPSBzZWxmLl9oYW5kbGVfZG9fcHV0CisKKyAgICBkZWYgX2hhbmRsZV9kb19wdXQoc2Vs
Zik6CisgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LnB1dF9ieXRlcyhzZWxmLl9yZWxw
YXRoLAorICAgICAgICAgICAgICAgIHNlbGYuX2JvZHlfYnl0ZXMsIHNlbGYuX21vZGUpCisgICAg
ICAgIHNlbGYucmVzcG9uc2UgPSBTbWFydFNlcnZlclJlc3BvbnNlKCgnb2snLCkpCisKKyAgICBk
ZWYgX2Rlc2VyaWFsaXNlX29mZnNldHMoc2VsZiwgdGV4dCk6CisgICAgICAgICMgWFhYOiBGSVhN
RSB0aGlzIHNob3VsZCBiZSBvbiB0aGUgcHJvdG9jb2wgb2JqZWN0LgorICAgICAgICBvZmZzZXRz
ID0gW10KKyAgICAgICAgZm9yIGxpbmUgaW4gdGV4dC5zcGxpdCgnXG4nKToKKyAgICAgICAgICAg
IGlmIG5vdCBsaW5lOgorICAgICAgICAgICAgICAgIGNvbnRpbnVlCisgICAgICAgICAgICBzdGFy
dCwgbGVuZ3RoID0gbGluZS5zcGxpdCgnLCcpCisgICAgICAgICAgICBvZmZzZXRzLmFwcGVuZCgo
aW50KHN0YXJ0KSwgaW50KGxlbmd0aCkpKQorICAgICAgICByZXR1cm4gb2Zmc2V0cworCisgICAg
ZGVmIGRvX3B1dF9ub25fYXRvbWljKHNlbGYsIHJlbHBhdGgsIG1vZGUsIGNyZWF0ZV9wYXJlbnQs
IGRpcl9tb2RlKToKKyAgICAgICAgc2VsZi5fY29udmVydGVkX2NvbW1hbmQgPSBUcnVlCisgICAg
ICAgIHNlbGYuX2VuZF9vZl9ib2R5X2hhbmRsZXIgPSBzZWxmLl9oYW5kbGVfcHV0X25vbl9hdG9t
aWMKKyAgICAgICAgc2VsZi5fcmVscGF0aCA9IHJlbHBhdGgKKyAgICAgICAgc2VsZi5fZGlyX21v
ZGUgPSBzZWxmLl9kZXNlcmlhbGlzZV9vcHRpb25hbF9tb2RlKGRpcl9tb2RlKQorICAgICAgICBz
ZWxmLl9tb2RlID0gc2VsZi5fZGVzZXJpYWxpc2Vfb3B0aW9uYWxfbW9kZShtb2RlKQorICAgICAg
ICAjIGEgYm9vbGVhbiB3b3VsZCBiZSBuaWNlciBYWFgKKyAgICAgICAgc2VsZi5fY3JlYXRlX3Bh
cmVudCA9IChjcmVhdGVfcGFyZW50ID09ICdUJykKKworICAgIGRlZiBfaGFuZGxlX3B1dF9ub25f
YXRvbWljKHNlbGYpOgorICAgICAgICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5wdXRfYnl0ZXNf
bm9uX2F0b21pYyhzZWxmLl9yZWxwYXRoLAorICAgICAgICAgICAgICAgIHNlbGYuX2JvZHlfYnl0
ZXMsCisgICAgICAgICAgICAgICAgbW9kZT1zZWxmLl9tb2RlLAorICAgICAgICAgICAgICAgIGNy
ZWF0ZV9wYXJlbnRfZGlyPXNlbGYuX2NyZWF0ZV9wYXJlbnQsCisgICAgICAgICAgICAgICAgZGly
X21vZGU9c2VsZi5fZGlyX21vZGUpCisgICAgICAgIHNlbGYucmVzcG9uc2UgPSBTbWFydFNlcnZl
clJlc3BvbnNlKCgnb2snLCkpCisKKyAgICBkZWYgZG9fcmVhZHYoc2VsZiwgcmVscGF0aCk6Cisg
ICAgICAgIHNlbGYuX2NvbnZlcnRlZF9jb21tYW5kID0gVHJ1ZQorICAgICAgICBzZWxmLl9lbmRf
b2ZfYm9keV9oYW5kbGVyID0gc2VsZi5faGFuZGxlX3JlYWR2X29mZnNldHMKKyAgICAgICAgc2Vs
Zi5fcmVscGF0aCA9IHJlbHBhdGgKKworICAgIGRlZiBlbmRfb2ZfYm9keShzZWxmKToKKyAgICAg
ICAgIiIiTm8gbW9yZSBib2R5IGRhdGEgd2lsbCBiZSByZWNlaXZlZC4iIiIKKyAgICAgICAgc2Vs
Zi5fcnVuX2hhbmRsZXJfY29kZShzZWxmLl9lbmRfb2ZfYm9keV9oYW5kbGVyLCAoKSwge30pCisg
ICAgICAgICMgY2Fubm90IHJlYWQgYWZ0ZXIgdGhpcy4KKyAgICAgICAgc2VsZi5maW5pc2hlZF9y
ZWFkaW5nID0gVHJ1ZQorCisgICAgZGVmIF9oYW5kbGVfcmVhZHZfb2Zmc2V0cyhzZWxmKToKKyAg
ICAgICAgIiIiYWNjZXB0IG9mZnNldHMgZm9yIGEgcmVhZHYgcmVxdWVzdC4iIiIKKyAgICAgICAg
b2Zmc2V0cyA9IHNlbGYuX2Rlc2VyaWFsaXNlX29mZnNldHMoc2VsZi5fYm9keV9ieXRlcykKKyAg
ICAgICAgYmFja2luZ19ieXRlcyA9ICcnLmpvaW4oYnl0ZXMgZm9yIG9mZnNldCwgYnl0ZXMgaW4K
KyAgICAgICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LnJlYWR2KHNlbGYuX3JlbHBhdGgs
IG9mZnNldHMpKQorICAgICAgICBzZWxmLnJlc3BvbnNlID0gU21hcnRTZXJ2ZXJSZXNwb25zZSgo
J3JlYWR2JywpLCBiYWNraW5nX2J5dGVzKQorICAgICAgICAKKyAgICBkZWYgZG9fcmVuYW1lKHNl
bGYsIHJlbF9mcm9tLCByZWxfdG8pOgorICAgICAgICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5y
ZW5hbWUocmVsX2Zyb20sIHJlbF90bykKKworICAgIGRlZiBkb19ybWRpcihzZWxmLCByZWxwYXRo
KToKKyAgICAgICAgc2VsZi5fYmFja2luZ190cmFuc3BvcnQucm1kaXIocmVscGF0aCkKKworICAg
IGRlZiBkb19zdGF0KHNlbGYsIHJlbHBhdGgpOgorICAgICAgICBzdGF0ID0gc2VsZi5fYmFja2lu
Z190cmFuc3BvcnQuc3RhdChyZWxwYXRoKQorICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNw
b25zZSgoJ3N0YXQnLCBzdHIoc3RhdC5zdF9zaXplKSwgb2N0KHN0YXQuc3RfbW9kZSkpKQorICAg
ICAgICAKKyAgICBkZWYgZG9fZ2V0X2J1bmRsZShzZWxmLCBwYXRoLCByZXZpc2lvbl9pZCk6Cisg
ICAgICAgICMgb3BlbiB0cmFuc3BvcnQgcmVsYXRpdmUgdG8gb3VyIGJhc2UKKyAgICAgICAgdCA9
IHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LmNsb25lKHBhdGgpCisgICAgICAgIGNvbnRyb2wsIGV4
dHJhX3BhdGggPSBienJkaXIuQnpyRGlyLm9wZW5fY29udGFpbmluZ19mcm9tX3RyYW5zcG9ydCh0
KQorICAgICAgICByZXBvID0gY29udHJvbC5vcGVuX3JlcG9zaXRvcnkoKQorICAgICAgICB0bXBm
ID0gdGVtcGZpbGUuVGVtcG9yYXJ5RmlsZSgpCisgICAgICAgIGJhc2VfcmV2aXNpb24gPSByZXZp
c2lvbi5OVUxMX1JFVklTSU9OCisgICAgICAgIHdyaXRlX2J1bmRsZShyZXBvLCByZXZpc2lvbl9p
ZCwgYmFzZV9yZXZpc2lvbiwgdG1wZikKKyAgICAgICAgdG1wZi5zZWVrKDApCisgICAgICAgIHJl
dHVybiBTbWFydFNlcnZlclJlc3BvbnNlKCgpLCB0bXBmLnJlYWQoKSkKKworICAgIGRlZiBkaXNw
YXRjaF9jb21tYW5kKHNlbGYsIGNtZCwgYXJncyk6CisgICAgICAgICIiIkRlcHJlY2F0ZWQgY29t
cGF0aWJpbGl0eSBtZXRob2QuIiIiICMgWFhYIFhYWAorICAgICAgICBmdW5jID0gZ2V0YXR0cihz
ZWxmLCAnZG9fJyArIGNtZCwgTm9uZSkKKyAgICAgICAgaWYgZnVuYyBpcyBOb25lOgorICAgICAg
ICAgICAgcmFpc2UgZXJyb3JzLlNtYXJ0UHJvdG9jb2xFcnJvcigiYmFkIHJlcXVlc3QgJXIiICUg
KGNtZCwpKQorICAgICAgICBzZWxmLl9ydW5faGFuZGxlcl9jb2RlKGZ1bmMsIGFyZ3MsIHt9KQor
CisgICAgZGVmIF9ydW5faGFuZGxlcl9jb2RlKHNlbGYsIGNhbGxhYmxlLCBhcmdzLCBrd2FyZ3Mp
OgorICAgICAgICAiIiJSdW4gc29tZSBoYW5kbGVyIHNwZWNpZmljIGNvZGUgJ2NhbGxhYmxlJy4K
KworICAgICAgICBJZiBhIHJlc3VsdCBpcyByZXR1cm5lZCwgaXQgaXMgY29uc2lkZXJlZCB0byBi
ZSB0aGUgY29tbWFuZHMgcmVzcG9uc2UsCisgICAgICAgIGFuZCBmaW5pc2hlZF9yZWFkaW5nIGlz
IHNldCB0cnVlLCBhbmQgaXRzIGFzc2lnbmVkIHRvIHNlbGYucmVzcG9uc2UuCisKKyAgICAgICAg
QW55IGV4Y2VwdGlvbnMgY2F1Z2h0IGFyZSB0cmFuc2xhdGVkIGFuZCBhIHJlc3BvbnNlIG9iamVj
dCBjcmVhdGVkCisgICAgICAgIGZyb20gdGhlbS4KKyAgICAgICAgIiIiCisgICAgICAgIHJlc3Vs
dCA9IHNlbGYuX2NhbGxfY29udmVydGluZ19lcnJvcnMoY2FsbGFibGUsIGFyZ3MsIGt3YXJncykK
KyAgICAgICAgaWYgcmVzdWx0IGlzIG5vdCBOb25lOgorICAgICAgICAgICAgc2VsZi5yZXNwb25z
ZSA9IHJlc3VsdAorICAgICAgICAgICAgc2VsZi5maW5pc2hlZF9yZWFkaW5nID0gVHJ1ZQorICAg
ICAgICAjIGhhbmRsZSB1bmNvbnZlcnRlZCBjb21tYW5kcworICAgICAgICBpZiBub3Qgc2VsZi5f
Y29udmVydGVkX2NvbW1hbmQ6CisgICAgICAgICAgICBzZWxmLmZpbmlzaGVkX3JlYWRpbmcgPSBU
cnVlCisgICAgICAgICAgICBpZiByZXN1bHQgaXMgTm9uZToKKyAgICAgICAgICAgICAgICBzZWxm
LnJlc3BvbnNlID0gU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ29rJywpKQorCisgICAgZGVmIF9jYWxs
X2NvbnZlcnRpbmdfZXJyb3JzKHNlbGYsIGNhbGxhYmxlLCBhcmdzLCBrd2FyZ3MpOgorICAgICAg
ICAiIiJDYWxsIGNhbGxhYmxlIGNvbnZlcnRpbmcgZXJyb3JzIHRvIFJlc3BvbnNlIG9iamVjdHMu
IiIiCisgICAgICAgIHRyeToKKyAgICAgICAgICAgIHJldHVybiBjYWxsYWJsZSgqYXJncywgKipr
d2FyZ3MpCisgICAgICAgIGV4Y2VwdCBlcnJvcnMuTm9TdWNoRmlsZSwgZToKKyAgICAgICAgICAg
IHJldHVybiBTbWFydFNlcnZlclJlc3BvbnNlKCgnTm9TdWNoRmlsZScsIGUucGF0aCkpCisgICAg
ICAgIGV4Y2VwdCBlcnJvcnMuRmlsZUV4aXN0cywgZToKKyAgICAgICAgICAgIHJldHVybiBTbWFy
dFNlcnZlclJlc3BvbnNlKCgnRmlsZUV4aXN0cycsIGUucGF0aCkpCisgICAgICAgIGV4Y2VwdCBl
cnJvcnMuRGlyZWN0b3J5Tm90RW1wdHksIGU6CisgICAgICAgICAgICByZXR1cm4gU21hcnRTZXJ2
ZXJSZXNwb25zZSgoJ0RpcmVjdG9yeU5vdEVtcHR5JywgZS5wYXRoKSkKKyAgICAgICAgZXhjZXB0
IGVycm9ycy5TaG9ydFJlYWR2RXJyb3IsIGU6CisgICAgICAgICAgICByZXR1cm4gU21hcnRTZXJ2
ZXJSZXNwb25zZSgoJ1Nob3J0UmVhZHZFcnJvcicsCisgICAgICAgICAgICAgICAgZS5wYXRoLCBz
dHIoZS5vZmZzZXQpLCBzdHIoZS5sZW5ndGgpLCBzdHIoZS5hY3R1YWwpKSkKKyAgICAgICAgZXhj
ZXB0IFVuaWNvZGVFcnJvciwgZToKKyAgICAgICAgICAgICMgSWYgaXQgaXMgYSBEZWNvZGVFcnJv
ciwgdGhhbiBtb3N0IGxpa2VseSB3ZSBhcmUgc3RhcnRpbmcKKyAgICAgICAgICAgICMgd2l0aCBh
IHBsYWluIHN0cmluZworICAgICAgICAgICAgc3RyX29yX3VuaWNvZGUgPSBlLm9iamVjdAorICAg
ICAgICAgICAgaWYgaXNpbnN0YW5jZShzdHJfb3JfdW5pY29kZSwgdW5pY29kZSk6CisgICAgICAg
ICAgICAgICAgIyBYWFg6IFVURi04IG1pZ2h0IGhhdmUgXHgwMSAob3VyIHNlcGVyYXRvciBieXRl
KSBpbiBpdC4gIFdlCisgICAgICAgICAgICAgICAgIyBzaG91bGQgZXNjYXBlIGl0IHNvbWVob3cu
CisgICAgICAgICAgICAgICAgdmFsID0gJ3U6JyArIHN0cl9vcl91bmljb2RlLmVuY29kZSgndXRm
LTgnKQorICAgICAgICAgICAgZWxzZToKKyAgICAgICAgICAgICAgICB2YWwgPSAnczonICsgc3Ry
X29yX3VuaWNvZGUuZW5jb2RlKCdiYXNlNjQnKQorICAgICAgICAgICAgIyBUaGlzIGhhbmRsZXMg
VW5pY29kZUVuY29kZUVycm9yIG9yIFVuaWNvZGVEZWNvZGVFcnJvcgorICAgICAgICAgICAgcmV0
dXJuIFNtYXJ0U2VydmVyUmVzcG9uc2UoKGUuX19jbGFzc19fLl9fbmFtZV9fLAorICAgICAgICAg
ICAgICAgICAgICBlLmVuY29kaW5nLCB2YWwsIHN0cihlLnN0YXJ0KSwgc3RyKGUuZW5kKSwgZS5y
ZWFzb24pKQorICAgICAgICBleGNlcHQgZXJyb3JzLlRyYW5zcG9ydE5vdFBvc3NpYmxlLCBlOgor
ICAgICAgICAgICAgaWYgZS5tc2cgPT0gInJlYWRvbmx5IHRyYW5zcG9ydCI6CisgICAgICAgICAg
ICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVzcG9uc2UoKCdSZWFkT25seUVycm9yJywgKSkKKyAg
ICAgICAgICAgIGVsc2U6CisgICAgICAgICAgICAgICAgcmFpc2UKKworCgo=

=== modified file bzrlib/smart/server.py // encoding:base64
LS0tIGJ6cmxpYi9zbWFydC9zZXJ2ZXIucHkKKysrIGJ6cmxpYi9zbWFydC9zZXJ2ZXIucHkKQEAg
LTI2LDcgKzI2LDcgQEAKICAgICB0cmFuc3BvcnQsCiAgICAgdXJsdXRpbHMsCiApCi1mcm9tIGJ6
cmxpYi50cmFuc3BvcnQucmVtb3RlIGltcG9ydCBTbWFydFNlcnZlclNvY2tldFN0cmVhbU1lZGl1
bQorZnJvbSBienJsaWIuc21hcnQubWVkaXVtIGltcG9ydCBTbWFydFNlcnZlclNvY2tldFN0cmVh
bU1lZGl1bQogCiAKIGNsYXNzIFNtYXJ0VENQU2VydmVyKG9iamVjdCk6Cgo=

=== modified file bzrlib/tests/HTTPTestUtil.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy9IVFRQVGVzdFV0aWwucHkKKysrIGJ6cmxpYi90ZXN0cy9IVFRQVGVz
dFV0aWwucHkKQEAgLTI4LDggKzI4LDggQEAKICAgICApCiBmcm9tIGJ6cmxpYi50cmFuc3BvcnQg
aW1wb3J0ICgKICAgICBnZXRfdHJhbnNwb3J0LAotICAgIHJlbW90ZSwKICAgICApCitmcm9tIGJ6
cmxpYi5zbWFydCBpbXBvcnQgcHJvdG9jb2wKIAogCiBjbGFzcyBXYWxsUmVxdWVzdEhhbmRsZXIo
VGVzdGluZ0hUVFBSZXF1ZXN0SGFuZGxlcik6CkBAIC0xMzAsNyArMTMwLDcgQEAKICAgICAgICAg
IyB3ZSBoYXZlIHRvIHN0b3AgZWFybHkgZHVlIHRvIGVycm9yLCBidXQgd2Ugd291bGQgYWxzbyBo
YXZlIHRvIHVzZSB0aGUKICAgICAgICAgIyBIVFRQIHRyYWlsZXIgZmFjaWxpdHkgd2hpY2ggbWF5
IG5vdCBiZSB3aWRlbHkgYXZhaWxhYmxlLgogICAgICAgICBvdXRfYnVmZmVyID0gU3RyaW5nSU8o
KQotICAgICAgICBzbWFydF9wcm90b2NvbF9yZXF1ZXN0ID0gcmVtb3RlLlNtYXJ0U2VydmVyUmVx
dWVzdFByb3RvY29sT25lKAorICAgICAgICBzbWFydF9wcm90b2NvbF9yZXF1ZXN0ID0gcHJvdG9j
b2wuU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoCiAgICAgICAgICAgICAgICAgdHJhbnNw
b3J0LCBvdXRfYnVmZmVyLndyaXRlKQogICAgICAgICAjIGlmIHRoaXMgZmFpbHMsIHdlIHNob3Vs
ZCByZXR1cm4gNDAwIGJhZCByZXF1ZXN0LCBidXQgZmFpbHVyZSBpcwogICAgICAgICAjIGZhaWx1
cmUgZm9yIG5vdyAtIFJCQyAyMDA2MDkxOQoK

=== modified file bzrlib/tests/test_smart_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NtYXJ0X3RyYW5zcG9ydC5weQorKysgYnpybGliL3Rlc3Rz
L3Rlc3Rfc21hcnRfdHJhbnNwb3J0LnB5CkBAIC0zMCw3ICszMCwxMiBAQAogICAgICAgICB0ZXN0
cywKICAgICAgICAgdXJsdXRpbHMsCiAgICAgICAgICkKLWZyb20gYnpybGliLnNtYXJ0IGltcG9y
dCBzZXJ2ZXIKK2Zyb20gYnpybGliLnNtYXJ0IGltcG9ydCAoCisgICAgICAgIG1lZGl1bSwKKyAg
ICAgICAgcHJvdG9jb2wsCisgICAgICAgIHJlcXVlc3QsCisgICAgICAgIHNlcnZlciwKKykKIGZy
b20gYnpybGliLnRlc3RzLkhUVFBUZXN0VXRpbCBpbXBvcnQgKAogICAgICAgICBIVFRQU2VydmVy
V2l0aFNtYXJ0cywKICAgICAgICAgU21hcnRSZXF1ZXN0SGFuZGxlciwKQEAgLTQzLDcgKzQ4LDYg
QEAKICAgICAgICAgKQogZnJvbSBienJsaWIudHJhbnNwb3J0Lmh0dHAgaW1wb3J0IFNtYXJ0Q2xp
ZW50SFRUUE1lZGl1bVJlcXVlc3QKIAotc21hcnQgPSByZW1vdGUKIAogY2xhc3MgU3RyaW5nSU9T
U0hWZW5kb3Iob2JqZWN0KToKICAgICAiIiJBIFNTSCB2ZW5kb3IgdGhhdCB1c2VzIFN0cmluZ0lP
IHRvIGJ1ZmZlciB3cml0ZXMgYW5kIGFuc3dlciByZWFkcy4iIiIKQEAgLTg3LDggKzkxLDggQEAK
ICAgICAgICAgc29jay5iaW5kKCgnMTI3LjAuMC4xJywgMCkpCiAgICAgICAgIHNvY2subGlzdGVu
KDEpCiAgICAgICAgIHBvcnQgPSBzb2NrLmdldHNvY2tuYW1lKClbMV0KLSAgICAgICAgbWVkaXVt
ID0gc21hcnQuU21hcnRUQ1BDbGllbnRNZWRpdW0oJzEyNy4wLjAuMScsIHBvcnQpCi0gICAgICAg
IHJldHVybiBzb2NrLCBtZWRpdW0KKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFy
dFRDUENsaWVudE1lZGl1bSgnMTI3LjAuMC4xJywgcG9ydCkKKyAgICAgICAgcmV0dXJuIHNvY2ss
IGNsaWVudF9tZWRpdW0KIAogICAgIGRlZiByZWNlaXZlX2J5dGVzX29uX3NlcnZlcihzZWxmLCBz
b2NrLCBieXRlcyk6CiAgICAgICAgICIiIkFjY2VwdCBhIGNvbm5lY3Rpb24gb24gc29jayBhbmQg
cmVhZCAzIGJ5dGVzLgpAQCAtMTEwLDI0ICsxMTQsMjQgQEAKICAgICAgICAgIyB0aGlzIGp1c3Qg
ZW5zdXJlcyB0aGF0IHRoZSBjb25zdHJ1Y3RvciBzdGF5cyBwYXJhbWV0ZXItZnJlZSB3aGljaAog
ICAgICAgICAjIGlzIGltcG9ydGFudCBmb3IgcmV1c2UgOiBzb21lIHN1YmNsYXNzZXMgd2lsbCBk
eW5hbWljYWxseSBjb25uZWN0LAogICAgICAgICAjIG90aGVycyBhcmUgYWx3YXlzIG9uLCBldGMu
Ci0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtKCkKKyAgICAg
ICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFydENsaWVudFN0cmVhbU1lZGl1bSgpCiAKICAg
ICBkZWYgdGVzdF9jb25zdHJ1Y3Rfc21hcnRfY2xpZW50X21lZGl1bShzZWxmKToKICAgICAgICAg
IyB0aGUgYmFzZSBjbGllbnQgbWVkaXVtIHRha2VzIG5vIHBhcmFtZXRlcnMKLSAgICAgICAgbWVk
aXVtID0gc21hcnQuU21hcnRDbGllbnRNZWRpdW0oKQorICAgICAgICBjbGllbnRfbWVkaXVtID0g
bWVkaXVtLlNtYXJ0Q2xpZW50TWVkaXVtKCkKICAgICAKICAgICBkZWYgdGVzdF9jb25zdHJ1Y3Rf
c21hcnRfc2ltcGxlX3BpcGVzX2NsaWVudF9tZWRpdW0oc2VsZik6CiAgICAgICAgICMgdGhlIFNp
bXBsZVBpcGVzIGNsaWVudCBtZWRpdW0gdGFrZXMgdHdvIHBpcGVzOgogICAgICAgICAjIHJlYWRh
YmxlIHBpcGUsIHdyaXRlYWJsZSBwaXBlLgogICAgICAgICAjIENvbnN0cnVjdGluZyBvbmUgc2hv
dWxkIGp1c3Qgc2F2ZSB0aGVzZSBhbmQgZG8gbm90aGluZy4KICAgICAgICAgIyBXZSB0ZXN0IHRo
aXMgYnkgcGFzc2luZyBpbiBOb25lLgotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBs
ZVBpcGVzQ2xpZW50TWVkaXVtKE5vbmUsIE5vbmUpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBt
ZWRpdW0uU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShOb25lLCBOb25lKQogICAgICAgICAK
ICAgICBkZWYgdGVzdF9zaW1wbGVfcGlwZXNfY2xpZW50X3JlcXVlc3RfdHlwZShzZWxmKToKICAg
ICAgICAgIyBTaW1wbGVQaXBlc0NsaWVudCBzaG91bGQgdXNlIFNtYXJ0Q2xpZW50U3RyZWFtTWVk
aXVtUmVxdWVzdCdzLgotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xp
ZW50TWVkaXVtKE5vbmUsIE5vbmUpCi0gICAgICAgIHJlcXVlc3QgPSBtZWRpdW0uZ2V0X3JlcXVl
c3QoKQotICAgICAgICBzZWxmLmFzc2VydElzSW5zdGFuY2UocmVxdWVzdCwgc21hcnQuU21hcnRD
bGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVt
LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oTm9uZSwgTm9uZSkKKyAgICAgICAgcmVxdWVz
dCA9IGNsaWVudF9tZWRpdW0uZ2V0X3JlcXVlc3QoKQorICAgICAgICBzZWxmLmFzc2VydElzSW5z
dGFuY2UocmVxdWVzdCwgbWVkaXVtLlNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtUmVxdWVzdCkKIAog
ICAgIGRlZiB0ZXN0X3NpbXBsZV9waXBlc19jbGllbnRfZ2V0X2NvbmN1cnJlbnRfcmVxdWVzdHMo
c2VsZik6CiAgICAgICAgICMgdGhlIHNpbXBsZV9waXBlcyBjbGllbnQgZG9lcyBub3Qgc3VwcG9y
dCBwaXBlbGluZWQgcmVxdWVzdHM6CkBAIC0xMzcsMzAgKzE0MSwzMCBAQAogICAgICAgICAjIGNs
YXNzZXMgLSBhcyB0aGUgc2libGluZyBjbGFzc2VzIHNoYXJlIHRoaXMgbG9naWMsIHRoZXkgZG8g
bm90IGhhdmUKICAgICAgICAgIyBleHBsaWNpdCB0ZXN0cyBmb3IgdGhpcy4KICAgICAgICAgb3V0
cHV0ID0gU3RyaW5nSU8oKQotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVz
Q2xpZW50TWVkaXVtKE5vbmUsIG91dHB1dCkKLSAgICAgICAgcmVxdWVzdCA9IG1lZGl1bS5nZXRf
cmVxdWVzdCgpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRTaW1wbGVQaXBl
c0NsaWVudE1lZGl1bShOb25lLCBvdXRwdXQpCisgICAgICAgIHJlcXVlc3QgPSBjbGllbnRfbWVk
aXVtLmdldF9yZXF1ZXN0KCkKICAgICAgICAgcmVxdWVzdC5maW5pc2hlZF93cml0aW5nKCkKICAg
ICAgICAgcmVxdWVzdC5maW5pc2hlZF9yZWFkaW5nKCkKLSAgICAgICAgcmVxdWVzdDIgPSBtZWRp
dW0uZ2V0X3JlcXVlc3QoKQorICAgICAgICByZXF1ZXN0MiA9IGNsaWVudF9tZWRpdW0uZ2V0X3Jl
cXVlc3QoKQogICAgICAgICByZXF1ZXN0Mi5maW5pc2hlZF93cml0aW5nKCkKICAgICAgICAgcmVx
dWVzdDIuZmluaXNoZWRfcmVhZGluZygpCiAKICAgICBkZWYgdGVzdF9zaW1wbGVfcGlwZXNfY2xp
ZW50X19hY2NlcHRfYnl0ZXNfd3JpdGVzX3RvX3dyaXRhYmxlKHNlbGYpOgogICAgICAgICAjIGFj
Y2VwdF9ieXRlcyB3cml0ZXMgdG8gdGhlIHdyaXRlYWJsZSBwaXBlLgogICAgICAgICBvdXRwdXQg
PSBTdHJpbmdJTygpCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U2ltcGxlUGlwZXNDbGll
bnRNZWRpdW0oTm9uZSwgb3V0cHV0KQotICAgICAgICBtZWRpdW0uX2FjY2VwdF9ieXRlcygnYWJj
JykKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFydFNpbXBsZVBpcGVzQ2xpZW50
TWVkaXVtKE5vbmUsIG91dHB1dCkKKyAgICAgICAgY2xpZW50X21lZGl1bS5fYWNjZXB0X2J5dGVz
KCdhYmMnKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdhYmMnLCBvdXRwdXQuZ2V0dmFsdWUo
KSkKICAgICAKICAgICBkZWYgdGVzdF9zaW1wbGVfcGlwZXNfY2xpZW50X2Rpc2Nvbm5lY3RfZG9l
c19ub3RoaW5nKHNlbGYpOgogICAgICAgICAjIGNhbGxpbmcgZGlzY29ubmVjdCBkb2VzIG5vdGhp
bmcuCiAgICAgICAgIGlucHV0ID0gU3RyaW5nSU8oKQogICAgICAgICBvdXRwdXQgPSBTdHJpbmdJ
TygpCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0o
aW5wdXQsIG91dHB1dCkKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFydFNpbXBs
ZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCiAgICAgICAgICMgc2VuZCBzb21lIGJ5
dGVzIHRvIGVuc3VyZSBkaXNjb25uZWN0aW5nIGFmdGVyIGFjdGl2aXR5IHN0aWxsIGRvZXMgbm90
CiAgICAgICAgICMgY2xvc2UuCi0gICAgICAgIG1lZGl1bS5fYWNjZXB0X2J5dGVzKCdhYmMnKQot
ICAgICAgICBtZWRpdW0uZGlzY29ubmVjdCgpCisgICAgICAgIGNsaWVudF9tZWRpdW0uX2FjY2Vw
dF9ieXRlcygnYWJjJykKKyAgICAgICAgY2xpZW50X21lZGl1bS5kaXNjb25uZWN0KCkKICAgICAg
ICAgc2VsZi5hc3NlcnRGYWxzZShpbnB1dC5jbG9zZWQpCiAgICAgICAgIHNlbGYuYXNzZXJ0RmFs
c2Uob3V0cHV0LmNsb3NlZCkKIApAQCAtMTY5LDEwICsxNzMsMTAgQEAKICAgICAgICAgIyBhY2Nl
cHRfYnl0ZXMgd3JpdGVzIHRvLgogICAgICAgICBpbnB1dCA9IFN0cmluZ0lPKCkKICAgICAgICAg
b3V0cHV0ID0gU3RyaW5nSU8oKQotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBp
cGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCi0gICAgICAgIG1lZGl1bS5fYWNjZXB0X2J5
dGVzKCdhYmMnKQotICAgICAgICBtZWRpdW0uZGlzY29ubmVjdCgpCi0gICAgICAgIG1lZGl1bS5f
YWNjZXB0X2J5dGVzKCdhYmMnKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0
U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKKyAgICAgICAgY2xpZW50X21l
ZGl1bS5fYWNjZXB0X2J5dGVzKCdhYmMnKQorICAgICAgICBjbGllbnRfbWVkaXVtLmRpc2Nvbm5l
Y3QoKQorICAgICAgICBjbGllbnRfbWVkaXVtLl9hY2NlcHRfYnl0ZXMoJ2FiYycpCiAgICAgICAg
IHNlbGYuYXNzZXJ0RmFsc2UoaW5wdXQuY2xvc2VkKQogICAgICAgICBzZWxmLmFzc2VydEZhbHNl
KG91dHB1dC5jbG9zZWQpCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJ2FiY2FiYycsIG91dHB1
dC5nZXR2YWx1ZSgpKQpAQCAtMTgwLDE3ICsxODQsMTcgQEAKICAgICBkZWYgdGVzdF9zaW1wbGVf
cGlwZXNfY2xpZW50X2lnbm9yZXNfZGlzY29ubmVjdF93aGVuX25vdF9jb25uZWN0ZWQoc2VsZik6
CiAgICAgICAgICMgRG9pbmcgYSBkaXNjb25uZWN0IG9uIGEgbmV3IChhbmQgdGh1cyB1bmNvbm5l
Y3RlZCkgU2ltcGxlUGlwZXMgbWVkaXVtCiAgICAgICAgICMgZG9lcyBub3RoaW5nLgotICAgICAg
ICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKE5vbmUsIE5vbmUp
Ci0gICAgICAgIG1lZGl1bS5kaXNjb25uZWN0KCkKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1l
ZGl1bS5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKE5vbmUsIE5vbmUpCisgICAgICAgIGNs
aWVudF9tZWRpdW0uZGlzY29ubmVjdCgpCiAKICAgICBkZWYgdGVzdF9zaW1wbGVfcGlwZXNfY2xp
ZW50X2Nhbl9hbHdheXNfcmVhZChzZWxmKToKICAgICAgICAgIyBTbWFydFNpbXBsZVBpcGVzQ2xp
ZW50TWVkaXVtIGlzIG5ldmVyIGRpc2Nvbm5lY3RlZCwgc28gcmVhZF9ieXRlcwogICAgICAgICAj
IGFsd2F5cyB0cmllcyB0byByZWFkIGZyb20gdGhlIHVuZGVybHlpbmcgcGlwZS4KICAgICAgICAg
aW5wdXQgPSBTdHJpbmdJTygnYWJjZGVmJykKLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRT
aW1wbGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwgTm9uZSkKLSAgICAgICAgc2VsZi5hc3NlcnRF
cXVhbCgnYWJjJywgbWVkaXVtLnJlYWRfYnl0ZXMoMykpCi0gICAgICAgIG1lZGl1bS5kaXNjb25u
ZWN0KCkKLSAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgnZGVmJywgbWVkaXVtLnJlYWRfYnl0ZXMo
MykpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRTaW1wbGVQaXBlc0NsaWVu
dE1lZGl1bShpbnB1dCwgTm9uZSkKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgnYWJjJywgY2xp
ZW50X21lZGl1bS5yZWFkX2J5dGVzKDMpKQorICAgICAgICBjbGllbnRfbWVkaXVtLmRpc2Nvbm5l
Y3QoKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdkZWYnLCBjbGllbnRfbWVkaXVtLnJlYWRf
Ynl0ZXMoMykpCiAgICAgICAgIAogICAgIGRlZiB0ZXN0X3NpbXBsZV9waXBlc19jbGllbnRfc3Vw
cG9ydHNfX2ZsdXNoKHNlbGYpOgogICAgICAgICAjIGludm9raW5nIF9mbHVzaCBvbiBhIFNpbXBs
ZVBpcGVzQ2xpZW50IHNob3VsZCBmbHVzaCB0aGUgb3V0cHV0IApAQCAtMjAyLDEyICsyMDYsMTIg
QEAKICAgICAgICAgZmx1c2hfY2FsbHMgPSBbXQogICAgICAgICBkZWYgbG9nZ2luZ19mbHVzaCgp
OiBmbHVzaF9jYWxscy5hcHBlbmQoJ2ZsdXNoJykKICAgICAgICAgb3V0cHV0LmZsdXNoID0gbG9n
Z2luZ19mbHVzaAotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50
TWVkaXVtKGlucHV0LCBvdXRwdXQpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21h
cnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwgb3V0cHV0KQogICAgICAgICAjIHRoaXMg
Y2FsbCBpcyBoZXJlIHRvIGVuc3VyZSB3ZSBvbmx5IGZsdXNoIG9uY2UsIG5vdCBvbiBldmVyeQog
ICAgICAgICAjIF9hY2NlcHRfYnl0ZXMgY2FsbC4KLSAgICAgICAgbWVkaXVtLl9hY2NlcHRfYnl0
ZXMoJ2FiYycpCi0gICAgICAgIG1lZGl1bS5fZmx1c2goKQotICAgICAgICBtZWRpdW0uZGlzY29u
bmVjdCgpCisgICAgICAgIGNsaWVudF9tZWRpdW0uX2FjY2VwdF9ieXRlcygnYWJjJykKKyAgICAg
ICAgY2xpZW50X21lZGl1bS5fZmx1c2goKQorICAgICAgICBjbGllbnRfbWVkaXVtLmRpc2Nvbm5l
Y3QoKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKFsnZmx1c2gnXSwgZmx1c2hfY2FsbHMpCiAK
ICAgICBkZWYgdGVzdF9jb25zdHJ1Y3Rfc21hcnRfc3NoX2NsaWVudF9tZWRpdW0oc2VsZik6CkBA
IC0yMjEsNyArMjI1LDcgQEAKICAgICAgICAgdW5vcGVuZWRfcG9ydCA9IHNvY2suZ2V0c29ja25h
bWUoKVsxXQogICAgICAgICAjIGhhdmluZyB2ZW5kb3IgYmUgaW52YWxpZCBtZWFucyB0aGF0IGlm
IGl0IHRyaWVzIHRvIGNvbm5lY3QgdmlhIHRoZQogICAgICAgICAjIHZlbmRvciBpdCB3aWxsIGJs
b3cgdXAuCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U1NIQ2xpZW50TWVkaXVtKCcxMjcu
MC4wLjEnLCB1bm9wZW5lZF9wb3J0LAorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNt
YXJ0U1NIQ2xpZW50TWVkaXVtKCcxMjcuMC4wLjEnLCB1bm9wZW5lZF9wb3J0LAogICAgICAgICAg
ICAgdXNlcm5hbWU9Tm9uZSwgcGFzc3dvcmQ9Tm9uZSwgdmVuZG9yPSJub3QgYSB2ZW5kb3IiKQog
ICAgICAgICBzb2NrLmNsb3NlKCkKIApAQCAtMjMwLDkgKzIzNCw5IEBACiAgICAgICAgICMgaXQg
Ynl0ZXMuCiAgICAgICAgIG91dHB1dCA9IFN0cmluZ0lPKCkKICAgICAgICAgdmVuZG9yID0gU3Ry
aW5nSU9TU0hWZW5kb3IoU3RyaW5nSU8oKSwgb3V0cHV0KQotICAgICAgICBtZWRpdW0gPSBzbWFy
dC5TbWFydFNTSENsaWVudE1lZGl1bSgnYSBob3N0bmFtZScsICdhIHBvcnQnLCAnYSB1c2VybmFt
ZScsCi0gICAgICAgICAgICAnYSBwYXNzd29yZCcsIHZlbmRvcikKLSAgICAgICAgbWVkaXVtLl9h
Y2NlcHRfYnl0ZXMoJ2FiYycpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRT
U0hDbGllbnRNZWRpdW0oCisgICAgICAgICAgICAnYSBob3N0bmFtZScsICdhIHBvcnQnLCAnYSB1
c2VybmFtZScsICdhIHBhc3N3b3JkJywgdmVuZG9yKQorICAgICAgICBjbGllbnRfbWVkaXVtLl9h
Y2NlcHRfYnl0ZXMoJ2FiYycpCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJ2FiYycsIG91dHB1
dC5nZXR2YWx1ZSgpKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKFsoJ2Nvbm5lY3Rfc3NoJywg
J2EgdXNlcm5hbWUnLCAnYSBwYXNzd29yZCcsCiAgICAgICAgICAgICAnYSBob3N0bmFtZScsICdh
IHBvcnQnLApAQCAtMjQ5LDkgKzI1Myw5IEBACiAgICAgICAgICAgICBvc3V0aWxzLnNldF9vcl91
bnNldF9lbnYoJ0JaUl9SRU1PVEVfUEFUSCcsIG9yaWdfYnpyX3JlbW90ZV9wYXRoKQogICAgICAg
ICBzZWxmLmFkZENsZWFudXAoY2xlYW51cF9lbnZpcm9uKQogICAgICAgICBvcy5lbnZpcm9uWydC
WlJfUkVNT1RFX1BBVEgnXSA9ICdmdWdseScKLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRT
U0hDbGllbnRNZWRpdW0oJ2EgaG9zdG5hbWUnLCAnYSBwb3J0JywgJ2EgdXNlcm5hbWUnLAorICAg
ICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U1NIQ2xpZW50TWVkaXVtKCdhIGhvc3Ru
YW1lJywgJ2EgcG9ydCcsICdhIHVzZXJuYW1lJywKICAgICAgICAgICAgICdhIHBhc3N3b3JkJywg
dmVuZG9yKQotICAgICAgICBtZWRpdW0uX2FjY2VwdF9ieXRlcygnYWJjJykKKyAgICAgICAgY2xp
ZW50X21lZGl1bS5fYWNjZXB0X2J5dGVzKCdhYmMnKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFs
KCdhYmMnLCBvdXRwdXQuZ2V0dmFsdWUoKSkKICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChbKCdj
b25uZWN0X3NzaCcsICdhIHVzZXJuYW1lJywgJ2EgcGFzc3dvcmQnLAogICAgICAgICAgICAgJ2Eg
aG9zdG5hbWUnLCAnYSBwb3J0JywKQEAgLTI2NCw5ICsyNjgsOSBAQAogICAgICAgICBpbnB1dCA9
IFN0cmluZ0lPKCkKICAgICAgICAgb3V0cHV0ID0gU3RyaW5nSU8oKQogICAgICAgICB2ZW5kb3Ig
PSBTdHJpbmdJT1NTSFZlbmRvcihpbnB1dCwgb3V0cHV0KQotICAgICAgICBtZWRpdW0gPSBzbWFy
dC5TbWFydFNTSENsaWVudE1lZGl1bSgnYSBob3N0bmFtZScsIHZlbmRvcj12ZW5kb3IpCi0gICAg
ICAgIG1lZGl1bS5fYWNjZXB0X2J5dGVzKCdhYmMnKQotICAgICAgICBtZWRpdW0uZGlzY29ubmVj
dCgpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRTU0hDbGllbnRNZWRpdW0o
J2EgaG9zdG5hbWUnLCB2ZW5kb3I9dmVuZG9yKQorICAgICAgICBjbGllbnRfbWVkaXVtLl9hY2Nl
cHRfYnl0ZXMoJ2FiYycpCisgICAgICAgIGNsaWVudF9tZWRpdW0uZGlzY29ubmVjdCgpCiAgICAg
ICAgIHNlbGYuYXNzZXJ0VHJ1ZShpbnB1dC5jbG9zZWQpCiAgICAgICAgIHNlbGYuYXNzZXJ0VHJ1
ZShvdXRwdXQuY2xvc2VkKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKFsKQEAgLTI4NCwxNyAr
Mjg4LDE3IEBACiAgICAgICAgIGlucHV0ID0gU3RyaW5nSU8oKQogICAgICAgICBvdXRwdXQgPSBT
dHJpbmdJTygpCiAgICAgICAgIHZlbmRvciA9IFN0cmluZ0lPU1NIVmVuZG9yKGlucHV0LCBvdXRw
dXQpCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U1NIQ2xpZW50TWVkaXVtKCdhIGhvc3Ru
YW1lJywgdmVuZG9yPXZlbmRvcikKLSAgICAgICAgbWVkaXVtLl9hY2NlcHRfYnl0ZXMoJ2FiYycp
Ci0gICAgICAgIG1lZGl1bS5kaXNjb25uZWN0KCkKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1l
ZGl1bS5TbWFydFNTSENsaWVudE1lZGl1bSgnYSBob3N0bmFtZScsIHZlbmRvcj12ZW5kb3IpCisg
ICAgICAgIGNsaWVudF9tZWRpdW0uX2FjY2VwdF9ieXRlcygnYWJjJykKKyAgICAgICAgY2xpZW50
X21lZGl1bS5kaXNjb25uZWN0KCkKICAgICAgICAgIyB0aGUgZGlzY29ubmVjdCBoYXMgY2xvc2Vk
IG91dHB1dCwgc28gd2UgbmVlZCBhIG5ldyBvdXRwdXQgZm9yIHRoZQogICAgICAgICAjIG5ldyBj
b25uZWN0aW9uIHRvIHdyaXRlIHRvLgogICAgICAgICBpbnB1dDIgPSBTdHJpbmdJTygpCiAgICAg
ICAgIG91dHB1dDIgPSBTdHJpbmdJTygpCiAgICAgICAgIHZlbmRvci5yZWFkX2Zyb20gPSBpbnB1
dDIKICAgICAgICAgdmVuZG9yLndyaXRlX3RvID0gb3V0cHV0MgotICAgICAgICBtZWRpdW0uX2Fj
Y2VwdF9ieXRlcygnYWJjJykKLSAgICAgICAgbWVkaXVtLmRpc2Nvbm5lY3QoKQorICAgICAgICBj
bGllbnRfbWVkaXVtLl9hY2NlcHRfYnl0ZXMoJ2FiYycpCisgICAgICAgIGNsaWVudF9tZWRpdW0u
ZGlzY29ubmVjdCgpCiAgICAgICAgIHNlbGYuYXNzZXJ0VHJ1ZShpbnB1dC5jbG9zZWQpCiAgICAg
ICAgIHNlbGYuYXNzZXJ0VHJ1ZShvdXRwdXQuY2xvc2VkKQogICAgICAgICBzZWxmLmFzc2VydFRy
dWUoaW5wdXQyLmNsb3NlZCkKQEAgLTMxMiwxNSArMzE2LDE1IEBACiAgICAgZGVmIHRlc3Rfc3No
X2NsaWVudF9pZ25vcmVzX2Rpc2Nvbm5lY3Rfd2hlbl9ub3RfY29ubmVjdGVkKHNlbGYpOgogICAg
ICAgICAjIERvaW5nIGEgZGlzY29ubmVjdCBvbiBhIG5ldyAoYW5kIHRodXMgdW5jb25uZWN0ZWQp
IFNTSCBtZWRpdW0KICAgICAgICAgIyBkb2VzIG5vdCBmYWlsLiAgSXQncyBvayB0byBkaXNjb25u
ZWN0IGFuIHVuY29ubmVjdGVkIG1lZGl1bS4KLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRT
U0hDbGllbnRNZWRpdW0oTm9uZSkKLSAgICAgICAgbWVkaXVtLmRpc2Nvbm5lY3QoKQorICAgICAg
ICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U1NIQ2xpZW50TWVkaXVtKE5vbmUpCisgICAg
ICAgIGNsaWVudF9tZWRpdW0uZGlzY29ubmVjdCgpCiAKICAgICBkZWYgdGVzdF9zc2hfY2xpZW50
X3JhaXNlc19vbl9yZWFkX3doZW5fbm90X2Nvbm5lY3RlZChzZWxmKToKICAgICAgICAgIyBEb2lu
ZyBhIHJlYWQgb24gYSBuZXcgKGFuZCB0aHVzIHVuY29ubmVjdGVkKSBTU0ggbWVkaXVtIHJhaXNl
cwogICAgICAgICAjIE1lZGl1bU5vdENvbm5lY3RlZC4KLSAgICAgICAgbWVkaXVtID0gc21hcnQu
U21hcnRTU0hDbGllbnRNZWRpdW0oTm9uZSkKLSAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoZXJy
b3JzLk1lZGl1bU5vdENvbm5lY3RlZCwgbWVkaXVtLnJlYWRfYnl0ZXMsIDApCi0gICAgICAgIHNl
bGYuYXNzZXJ0UmFpc2VzKGVycm9ycy5NZWRpdW1Ob3RDb25uZWN0ZWQsIG1lZGl1bS5yZWFkX2J5
dGVzLCAxKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U1NIQ2xpZW50TWVk
aXVtKE5vbmUpCisgICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKGVycm9ycy5NZWRpdW1Ob3RDb25u
ZWN0ZWQsIGNsaWVudF9tZWRpdW0ucmVhZF9ieXRlcywgMCkKKyAgICAgICAgc2VsZi5hc3NlcnRS
YWlzZXMoZXJyb3JzLk1lZGl1bU5vdENvbm5lY3RlZCwgY2xpZW50X21lZGl1bS5yZWFkX2J5dGVz
LCAxKQogCiAgICAgZGVmIHRlc3Rfc3NoX2NsaWVudF9zdXBwb3J0c19fZmx1c2goc2VsZik6CiAg
ICAgICAgICMgaW52b2tpbmcgX2ZsdXNoIG9uIGEgU1NIQ2xpZW50TWVkaXVtIHNob3VsZCBmbHVz
aCB0aGUgb3V0cHV0IApAQCAtMzMzLDEyICszMzcsMTIgQEAKICAgICAgICAgZGVmIGxvZ2dpbmdf
Zmx1c2goKTogZmx1c2hfY2FsbHMuYXBwZW5kKCdmbHVzaCcpCiAgICAgICAgIG91dHB1dC5mbHVz
aCA9IGxvZ2dpbmdfZmx1c2gKICAgICAgICAgdmVuZG9yID0gU3RyaW5nSU9TU0hWZW5kb3IoaW5w
dXQsIG91dHB1dCkKLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRTU0hDbGllbnRNZWRpdW0o
J2EgaG9zdG5hbWUnLCB2ZW5kb3I9dmVuZG9yKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVk
aXVtLlNtYXJ0U1NIQ2xpZW50TWVkaXVtKCdhIGhvc3RuYW1lJywgdmVuZG9yPXZlbmRvcikKICAg
ICAgICAgIyB0aGlzIGNhbGwgaXMgaGVyZSB0byBlbnN1cmUgd2Ugb25seSBmbHVzaCBvbmNlLCBu
b3Qgb24gZXZlcnkKICAgICAgICAgIyBfYWNjZXB0X2J5dGVzIGNhbGwuCi0gICAgICAgIG1lZGl1
bS5fYWNjZXB0X2J5dGVzKCdhYmMnKQotICAgICAgICBtZWRpdW0uX2ZsdXNoKCkKLSAgICAgICAg
bWVkaXVtLmRpc2Nvbm5lY3QoKQorICAgICAgICBjbGllbnRfbWVkaXVtLl9hY2NlcHRfYnl0ZXMo
J2FiYycpCisgICAgICAgIGNsaWVudF9tZWRpdW0uX2ZsdXNoKCkKKyAgICAgICAgY2xpZW50X21l
ZGl1bS5kaXNjb25uZWN0KCkKICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChbJ2ZsdXNoJ10sIGZs
dXNoX2NhbGxzKQogICAgICAgICAKICAgICBkZWYgdGVzdF9jb25zdHJ1Y3Rfc21hcnRfdGNwX2Ns
aWVudF9tZWRpdW0oc2VsZik6CkBAIC0zNDcsNyArMzUxLDcgQEAKICAgICAgICAgc29jayA9IHNv
Y2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQsIHNvY2tldC5TT0NLX1NUUkVBTSkKICAgICAgICAg
c29jay5iaW5kKCgnMTI3LjAuMC4xJywgMCkpCiAgICAgICAgIHVub3BlbmVkX3BvcnQgPSBzb2Nr
LmdldHNvY2tuYW1lKClbMV0KLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRUQ1BDbGllbnRN
ZWRpdW0oJzEyNy4wLjAuMScsIHVub3BlbmVkX3BvcnQpCisgICAgICAgIGNsaWVudF9tZWRpdW0g
PSBtZWRpdW0uU21hcnRUQ1BDbGllbnRNZWRpdW0oJzEyNy4wLjAuMScsIHVub3BlbmVkX3BvcnQp
CiAgICAgICAgIHNvY2suY2xvc2UoKQogCiAgICAgZGVmIHRlc3RfdGNwX2NsaWVudF9jb25uZWN0
c19vbl9maXJzdF91c2Uoc2VsZik6CkBAIC0zODAsMTUgKzM4NCwxNSBAQAogICAgIGRlZiB0ZXN0
X3RjcF9jbGllbnRfaWdub3Jlc19kaXNjb25uZWN0X3doZW5fbm90X2Nvbm5lY3RlZChzZWxmKToK
ICAgICAgICAgIyBEb2luZyBhIGRpc2Nvbm5lY3Qgb24gYSBuZXcgKGFuZCB0aHVzIHVuY29ubmVj
dGVkKSBUQ1AgbWVkaXVtCiAgICAgICAgICMgZG9lcyBub3QgZmFpbC4gIEl0J3Mgb2sgdG8gZGlz
Y29ubmVjdCBhbiB1bmNvbm5lY3RlZCBtZWRpdW0uCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNt
YXJ0VENQQ2xpZW50TWVkaXVtKE5vbmUsIE5vbmUpCi0gICAgICAgIG1lZGl1bS5kaXNjb25uZWN0
KCkKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFydFRDUENsaWVudE1lZGl1bShO
b25lLCBOb25lKQorICAgICAgICBjbGllbnRfbWVkaXVtLmRpc2Nvbm5lY3QoKQogCiAgICAgZGVm
IHRlc3RfdGNwX2NsaWVudF9yYWlzZXNfb25fcmVhZF93aGVuX25vdF9jb25uZWN0ZWQoc2VsZik6
CiAgICAgICAgICMgRG9pbmcgYSByZWFkIG9uIGEgbmV3IChhbmQgdGh1cyB1bmNvbm5lY3RlZCkg
VENQIG1lZGl1bSByYWlzZXMKICAgICAgICAgIyBNZWRpdW1Ob3RDb25uZWN0ZWQuCi0gICAgICAg
IG1lZGl1bSA9IHNtYXJ0LlNtYXJ0VENQQ2xpZW50TWVkaXVtKE5vbmUsIE5vbmUpCi0gICAgICAg
IHNlbGYuYXNzZXJ0UmFpc2VzKGVycm9ycy5NZWRpdW1Ob3RDb25uZWN0ZWQsIG1lZGl1bS5yZWFk
X2J5dGVzLCAwKQotICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhlcnJvcnMuTWVkaXVtTm90Q29u
bmVjdGVkLCBtZWRpdW0ucmVhZF9ieXRlcywgMSkKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1l
ZGl1bS5TbWFydFRDUENsaWVudE1lZGl1bShOb25lLCBOb25lKQorICAgICAgICBzZWxmLmFzc2Vy
dFJhaXNlcyhlcnJvcnMuTWVkaXVtTm90Q29ubmVjdGVkLCBjbGllbnRfbWVkaXVtLnJlYWRfYnl0
ZXMsIDApCisgICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKGVycm9ycy5NZWRpdW1Ob3RDb25uZWN0
ZWQsIGNsaWVudF9tZWRpdW0ucmVhZF9ieXRlcywgMSkKIAogICAgIGRlZiB0ZXN0X3RjcF9jbGll
bnRfc3VwcG9ydHNfX2ZsdXNoKHNlbGYpOgogICAgICAgICAjIGludm9raW5nIF9mbHVzaCBvbiBh
IFRDUENsaWVudE1lZGl1bSBzaG91bGQgZG8gc29tZXRoaW5nIHVzZWZ1bC4KQEAgLTQyMyw4ICs0
MjcsOCBAQAogICAgICAgICAjIFdyaXRpbmdDb21wbGV0ZWQgdG8gcHJldmVudCBiYWQgYXNzdW1w
dGlvbnMgb24gc3RyZWFtIGVudmlyb25tZW50cwogICAgICAgICAjIGJyZWFraW5nIHRoZSBuZWVk
cyBvZiBtZXNzYWdlLWJhc2VkIGVudmlyb25tZW50cy4KICAgICAgICAgb3V0cHV0ID0gU3RyaW5n
SU8oKQotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVt
KE5vbmUsIG91dHB1dCkKLSAgICAgICAgcmVxdWVzdCA9IHNtYXJ0LlNtYXJ0Q2xpZW50U3RyZWFt
TWVkaXVtUmVxdWVzdChtZWRpdW0pCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21h
cnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShOb25lLCBvdXRwdXQpCisgICAgICAgIHJlcXVlc3Qg
PSBtZWRpdW0uU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KGNsaWVudF9tZWRpdW0pCiAg
ICAgICAgIHJlcXVlc3QuZmluaXNoZWRfd3JpdGluZygpCiAgICAgICAgIHNlbGYuYXNzZXJ0UmFp
c2VzKGVycm9ycy5Xcml0aW5nQ29tcGxldGVkLCByZXF1ZXN0LmFjY2VwdF9ieXRlcywgTm9uZSkK
IApAQCAtNDM0LDggKzQzOCw4IEBACiAgICAgICAgICMgYW5kIGNoZWNraW5nIHRoYXQgdGhlIHBp
cGVzIGdldCB0aGUgZGF0YS4KICAgICAgICAgaW5wdXQgPSBTdHJpbmdJTygpCiAgICAgICAgIG91
dHB1dCA9IFN0cmluZ0lPKCkKLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRTaW1wbGVQaXBl
c0NsaWVudE1lZGl1bShpbnB1dCwgb3V0cHV0KQotICAgICAgICByZXF1ZXN0ID0gc21hcnQuU21h
cnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KG1lZGl1bSkKKyAgICAgICAgY2xpZW50X21lZGl1
bSA9IG1lZGl1bS5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCisg
ICAgICAgIHJlcXVlc3QgPSBtZWRpdW0uU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KGNs
aWVudF9tZWRpdW0pCiAgICAgICAgIHJlcXVlc3QuYWNjZXB0X2J5dGVzKCcxMjMnKQogICAgICAg
ICByZXF1ZXN0LmZpbmlzaGVkX3dyaXRpbmcoKQogICAgICAgICByZXF1ZXN0LmZpbmlzaGVkX3Jl
YWRpbmcoKQpAQCAtNDQ2LDM0ICs0NTAsMzQgQEAKICAgICAgICAgIyBjb25zdHJ1Y3RpbmcgYSBT
bWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVlc3Qgb24gYSBTdHJlYW1NZWRpdW0gc2V0cwogICAg
ICAgICAjIHRoZSBjdXJyZW50IHJlcXVlc3QgdG8gdGhlIG5ldyBTbWFydENsaWVudFN0cmVhbU1l
ZGl1bVJlcXVlc3QKICAgICAgICAgb3V0cHV0ID0gU3RyaW5nSU8oKQotICAgICAgICBtZWRpdW0g
PSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKE5vbmUsIG91dHB1dCkKLSAgICAg
ICAgcmVxdWVzdCA9IHNtYXJ0LlNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtUmVxdWVzdChtZWRpdW0p
Ci0gICAgICAgIHNlbGYuYXNzZXJ0SXMobWVkaXVtLl9jdXJyZW50X3JlcXVlc3QsIHJlcXVlc3Qp
CisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRTaW1wbGVQaXBlc0NsaWVudE1l
ZGl1bShOb25lLCBvdXRwdXQpCisgICAgICAgIHJlcXVlc3QgPSBtZWRpdW0uU21hcnRDbGllbnRT
dHJlYW1NZWRpdW1SZXF1ZXN0KGNsaWVudF9tZWRpdW0pCisgICAgICAgIHNlbGYuYXNzZXJ0SXMo
Y2xpZW50X21lZGl1bS5fY3VycmVudF9yZXF1ZXN0LCByZXF1ZXN0KQogCiAgICAgZGVmIHRlc3Rf
Y29uc3RydWN0X3doaWxlX2Fub3RoZXJfcmVxdWVzdF9hY3RpdmVfdGhyb3dzKHNlbGYpOgogICAg
ICAgICAjIGNvbnN0cnVjdGluZyBhIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtUmVxdWVzdCBvbiBh
IFN0cmVhbU1lZGl1bSB3aXRoCiAgICAgICAgICMgYSBub24tTm9uZSBfY3VycmVudF9yZXF1ZXN0
IHJhaXNlcyBUb29NYW55Q29uY3VycmVudFJlcXVlc3RzLgogICAgICAgICBvdXRwdXQgPSBTdHJp
bmdJTygpCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRp
dW0oTm9uZSwgb3V0cHV0KQotICAgICAgICBtZWRpdW0uX2N1cnJlbnRfcmVxdWVzdCA9ICJhIgor
ICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRp
dW0oTm9uZSwgb3V0cHV0KQorICAgICAgICBjbGllbnRfbWVkaXVtLl9jdXJyZW50X3JlcXVlc3Qg
PSAiYSIKICAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoZXJyb3JzLlRvb01hbnlDb25jdXJyZW50
UmVxdWVzdHMsCi0gICAgICAgICAgICBzbWFydC5TbWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVl
c3QsIG1lZGl1bSkKKyAgICAgICAgICAgIG1lZGl1bS5TbWFydENsaWVudFN0cmVhbU1lZGl1bVJl
cXVlc3QsIGNsaWVudF9tZWRpdW0pCiAKICAgICBkZWYgdGVzdF9maW5pc2hlZF9yZWFkX2NsZWFy
c19jdXJyZW50X3JlcXVlc3Qoc2VsZik6CiAgICAgICAgICMgY2FsbGluZyBmaW5pc2hlZF9yZWFk
aW5nIGNsZWFycyB0aGUgY3VycmVudCByZXF1ZXN0IGZyb20gdGhlIHJlcXVlc3RzCiAgICAgICAg
ICMgbWVkaXVtCiAgICAgICAgIG91dHB1dCA9IFN0cmluZ0lPKCkKLSAgICAgICAgbWVkaXVtID0g
c21hcnQuU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShOb25lLCBvdXRwdXQpCi0gICAgICAg
IHJlcXVlc3QgPSBzbWFydC5TbWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVlc3QobWVkaXVtKQor
ICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRp
dW0oTm9uZSwgb3V0cHV0KQorICAgICAgICByZXF1ZXN0ID0gbWVkaXVtLlNtYXJ0Q2xpZW50U3Ry
ZWFtTWVkaXVtUmVxdWVzdChjbGllbnRfbWVkaXVtKQogICAgICAgICByZXF1ZXN0LmZpbmlzaGVk
X3dyaXRpbmcoKQogICAgICAgICByZXF1ZXN0LmZpbmlzaGVkX3JlYWRpbmcoKQotICAgICAgICBz
ZWxmLmFzc2VydEVxdWFsKE5vbmUsIG1lZGl1bS5fY3VycmVudF9yZXF1ZXN0KQorICAgICAgICBz
ZWxmLmFzc2VydEVxdWFsKE5vbmUsIGNsaWVudF9tZWRpdW0uX2N1cnJlbnRfcmVxdWVzdCkKIAog
ICAgIGRlZiB0ZXN0X2ZpbmlzaGVkX3JlYWRfYmVmb3JlX2ZpbmlzaGVkX3dyaXRlX2Vycm9ycyhz
ZWxmKToKICAgICAgICAgIyBjYWxsaW5nIGZpbmlzaGVkX3JlYWRpbmcgYmVmb3JlIGNhbGxpbmcg
ZmluaXNoZWRfd3JpdGluZyB0cmlnZ2VycyBhCiAgICAgICAgICMgV3JpdGluZ05vdENvbXBsZXRl
IGVycm9yLgotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVk
aXVtKE5vbmUsIE5vbmUpCi0gICAgICAgIHJlcXVlc3QgPSBzbWFydC5TbWFydENsaWVudFN0cmVh
bU1lZGl1bVJlcXVlc3QobWVkaXVtKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNt
YXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oTm9uZSwgTm9uZSkKKyAgICAgICAgcmVxdWVzdCA9
IG1lZGl1bS5TbWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVlc3QoY2xpZW50X21lZGl1bSkKICAg
ICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoZXJyb3JzLldyaXRpbmdOb3RDb21wbGV0ZSwgcmVxdWVz
dC5maW5pc2hlZF9yZWFkaW5nKQogICAgICAgICAKICAgICBkZWYgdGVzdF9yZWFkX2J5dGVzKHNl
bGYpOgpAQCAtNDg1LDggKzQ4OSw4IEBACiAgICAgICAgICMgc21va2UgdGVzdHMuCiAgICAgICAg
IGlucHV0ID0gU3RyaW5nSU8oJzMyMScpCiAgICAgICAgIG91dHB1dCA9IFN0cmluZ0lPKCkKLSAg
ICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwg
b3V0cHV0KQotICAgICAgICByZXF1ZXN0ID0gc21hcnQuU21hcnRDbGllbnRTdHJlYW1NZWRpdW1S
ZXF1ZXN0KG1lZGl1bSkKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFydFNpbXBs
ZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCisgICAgICAgIHJlcXVlc3QgPSBtZWRp
dW0uU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KGNsaWVudF9tZWRpdW0pCiAgICAgICAg
IHJlcXVlc3QuZmluaXNoZWRfd3JpdGluZygpCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJzMy
MScsIHJlcXVlc3QucmVhZF9ieXRlcygzKSkKICAgICAgICAgcmVxdWVzdC5maW5pc2hlZF9yZWFk
aW5nKCkKQEAgLTQ5OCw4ICs1MDIsOCBAQAogICAgICAgICAjIFdyaXRpbmdOb3RDb21wbGV0ZSBl
cnJvciBiZWNhdXNlIHRoZSBTbWFydCBwcm90b2NvbCBpcyBkZXNpZ25lZCB0byBiZQogICAgICAg
ICAjIGNvbXBhdGlibGUgd2l0aCBzdHJpY3QgbWVzc2FnZSBiYXNlZCBwcm90b2NvbHMgbGlrZSBI
VFRQIHdoZXJlIHRoZQogICAgICAgICAjIHJlcXVlc3QgY2Fubm90IGJlIHN1Ym1pdHRlZCB1bnRp
bCB0aGUgd3JpdGluZyBoYXMgY29tcGxldGVkLgotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFy
dFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKE5vbmUsIE5vbmUpCi0gICAgICAgIHJlcXVlc3QgPSBz
bWFydC5TbWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVlc3QobWVkaXVtKQorICAgICAgICBjbGll
bnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oTm9uZSwgTm9u
ZSkKKyAgICAgICAgcmVxdWVzdCA9IG1lZGl1bS5TbWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVl
c3QoY2xpZW50X21lZGl1bSkKICAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoZXJyb3JzLldyaXRp
bmdOb3RDb21wbGV0ZSwgcmVxdWVzdC5yZWFkX2J5dGVzLCBOb25lKQogCiAgICAgZGVmIHRlc3Rf
cmVhZF9ieXRlc19hZnRlcl9maW5pc2hlZF9yZWFkaW5nX2Vycm9ycyhzZWxmKToKQEAgLTUwNyw4
ICs1MTEsOCBAQAogICAgICAgICAjIFJlYWRpbmdDb21wbGV0ZWQgdG8gcHJldmVudCBiYWQgYXNz
dW1wdGlvbnMgb24gc3RyZWFtIGVudmlyb25tZW50cwogICAgICAgICAjIGJyZWFraW5nIHRoZSBu
ZWVkcyBvZiBtZXNzYWdlLWJhc2VkIGVudmlyb25tZW50cy4KICAgICAgICAgb3V0cHV0ID0gU3Ry
aW5nSU8oKQotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVk
aXVtKE5vbmUsIG91dHB1dCkKLSAgICAgICAgcmVxdWVzdCA9IHNtYXJ0LlNtYXJ0Q2xpZW50U3Ry
ZWFtTWVkaXVtUmVxdWVzdChtZWRpdW0pCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRpdW0u
U21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShOb25lLCBvdXRwdXQpCisgICAgICAgIHJlcXVl
c3QgPSBtZWRpdW0uU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KGNsaWVudF9tZWRpdW0p
CiAgICAgICAgIHJlcXVlc3QuZmluaXNoZWRfd3JpdGluZygpCiAgICAgICAgIHJlcXVlc3QuZmlu
aXNoZWRfcmVhZGluZygpCiAgICAgICAgIHNlbGYuYXNzZXJ0UmFpc2VzKGVycm9ycy5SZWFkaW5n
Q29tcGxldGVkLCByZXF1ZXN0LnJlYWRfYnl0ZXMsIE5vbmUpCkBAIC01MjksMTMgKzUzMywxMyBA
QAogCiAgICAgZGVmIHRlc3RfcHJvYmVfdHJhbnNwb3J0KHNlbGYpOgogICAgICAgICB0ID0gc2Vs
Zi5nZXRfdHJhbnNwb3J0KCkKLSAgICAgICAgc2VsZi5hc3NlcnRJc0luc3RhbmNlKHQsIHNtYXJ0
LlNtYXJ0VHJhbnNwb3J0KQorICAgICAgICBzZWxmLmFzc2VydElzSW5zdGFuY2UodCwgcmVtb3Rl
LlNtYXJ0VHJhbnNwb3J0KQogCiAgICAgZGVmIHRlc3RfZ2V0X21lZGl1bV9mcm9tX3RyYW5zcG9y
dChzZWxmKToKICAgICAgICAgIiIiUmVtb3RlIHRyYW5zcG9ydCBoYXMgYSBtZWRpdW0gYWx3YXlz
LCB3aGljaCBpdCBjYW4gcmV0dXJuLiIiIgogICAgICAgICB0ID0gc2VsZi5nZXRfdHJhbnNwb3J0
KCkKLSAgICAgICAgbWVkaXVtID0gdC5nZXRfc21hcnRfbWVkaXVtKCkKLSAgICAgICAgc2VsZi5h
c3NlcnRJc0luc3RhbmNlKG1lZGl1bSwgc21hcnQuU21hcnRDbGllbnRNZWRpdW0pCisgICAgICAg
IHNtYXJ0X21lZGl1bSA9IHQuZ2V0X3NtYXJ0X21lZGl1bSgpCisgICAgICAgIHNlbGYuYXNzZXJ0
SXNJbnN0YW5jZShzbWFydF9tZWRpdW0sIG1lZGl1bS5TbWFydENsaWVudE1lZGl1bSkKIAogCiBj
bGFzcyBFcnJvclJhaXNpbmdQcm90b2NvbChvYmplY3QpOgpAQCAtNTkwLDExICs1OTQsMTEgQEAK
ICAgICAgICAgdG9fc2VydmVyID0gU3RyaW5nSU8oJ2hlbGxvXG4nKQogICAgICAgICBmcm9tX3Nl
cnZlciA9IFN0cmluZ0lPKCkKICAgICAgICAgdHJhbnNwb3J0ID0gbG9jYWwuTG9jYWxUcmFuc3Bv
cnQodXJsdXRpbHMubG9jYWxfcGF0aF90b191cmwoJy8nKSkKLSAgICAgICAgc2VydmVyID0gc21h
cnQuU21hcnRTZXJ2ZXJQaXBlU3RyZWFtTWVkaXVtKAorICAgICAgICBzZXJ2ZXIgPSBtZWRpdW0u
U21hcnRTZXJ2ZXJQaXBlU3RyZWFtTWVkaXVtKAogICAgICAgICAgICAgdG9fc2VydmVyLCBmcm9t
X3NlcnZlciwgdHJhbnNwb3J0KQotICAgICAgICBwcm90b2NvbCA9IHNtYXJ0LlNtYXJ0U2VydmVy
UmVxdWVzdFByb3RvY29sT25lKHRyYW5zcG9ydCwKKyAgICAgICAgc21hcnRfcHJvdG9jb2wgPSBw
cm90b2NvbC5TbWFydFNlcnZlclJlcXVlc3RQcm90b2NvbE9uZSh0cmFuc3BvcnQsCiAgICAgICAg
ICAgICAgICAgZnJvbV9zZXJ2ZXIud3JpdGUpCi0gICAgICAgIHNlcnZlci5fc2VydmVfb25lX3Jl
cXVlc3QocHJvdG9jb2wpCisgICAgICAgIHNlcnZlci5fc2VydmVfb25lX3JlcXVlc3Qoc21hcnRf
cHJvdG9jb2wpCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJ29rXDAwMTFcbicsCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgZnJvbV9zZXJ2ZXIuZ2V0dmFsdWUoKSkKIApAQCAtNjAzLDExICs2
MDcsMTEgQEAKICAgICAgICAgdHJhbnNwb3J0LnB1dF9ieXRlcygndGVzdGZpbGUnLCAnY29udGVu
dHNcbm9mXG5maWxlXG4nKQogICAgICAgICB0b19zZXJ2ZXIgPSBTdHJpbmdJTygnZ2V0XDAwMS4v
dGVzdGZpbGVcbicpCiAgICAgICAgIGZyb21fc2VydmVyID0gU3RyaW5nSU8oKQotICAgICAgICBz
ZXJ2ZXIgPSBzbWFydC5TbWFydFNlcnZlclBpcGVTdHJlYW1NZWRpdW0oCisgICAgICAgIHNlcnZl
ciA9IG1lZGl1bS5TbWFydFNlcnZlclBpcGVTdHJlYW1NZWRpdW0oCiAgICAgICAgICAgICB0b19z
ZXJ2ZXIsIGZyb21fc2VydmVyLCB0cmFuc3BvcnQpCi0gICAgICAgIHByb3RvY29sID0gc21hcnQu
U21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUodHJhbnNwb3J0LAorICAgICAgICBzbWFydF9w
cm90b2NvbCA9IHByb3RvY29sLlNtYXJ0U2VydmVyUmVxdWVzdFByb3RvY29sT25lKHRyYW5zcG9y
dCwKICAgICAgICAgICAgICAgICBmcm9tX3NlcnZlci53cml0ZSkKLSAgICAgICAgc2VydmVyLl9z
ZXJ2ZV9vbmVfcmVxdWVzdChwcm90b2NvbCkKKyAgICAgICAgc2VydmVyLl9zZXJ2ZV9vbmVfcmVx
dWVzdChzbWFydF9wcm90b2NvbCkKICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgnb2tcbicKICAg
ICAgICAgICAgICAgICAgICAgICAgICAnMTdcbicKICAgICAgICAgICAgICAgICAgICAgICAgICAn
Y29udGVudHNcbm9mXG5maWxlXG4nCkBAIC02MjEsMTEgKzYyNSwxMSBAQAogICAgICAgICB0cmFu
c3BvcnQucHV0X2J5dGVzKHV0ZjhfZmlsZW5hbWUsICdjb250ZW50c1xub2ZcbmZpbGVcbicpCiAg
ICAgICAgIHRvX3NlcnZlciA9IFN0cmluZ0lPKCdnZXRcMDAxJyArIHV0ZjhfZmlsZW5hbWUgKyAn
XG4nKQogICAgICAgICBmcm9tX3NlcnZlciA9IFN0cmluZ0lPKCkKLSAgICAgICAgc2VydmVyID0g
c21hcnQuU21hcnRTZXJ2ZXJQaXBlU3RyZWFtTWVkaXVtKAorICAgICAgICBzZXJ2ZXIgPSBtZWRp
dW0uU21hcnRTZXJ2ZXJQaXBlU3RyZWFtTWVkaXVtKAogICAgICAgICAgICAgdG9fc2VydmVyLCBm
cm9tX3NlcnZlciwgdHJhbnNwb3J0KQotICAgICAgICBwcm90b2NvbCA9IHNtYXJ0LlNtYXJ0U2Vy
dmVyUmVxdWVzdFByb3RvY29sT25lKHRyYW5zcG9ydCwKKyAgICAgICAgc21hcnRfcHJvdG9jb2wg
PSBwcm90b2NvbC5TbWFydFNlcnZlclJlcXVlc3RQcm90b2NvbE9uZSh0cmFuc3BvcnQsCiAgICAg
ICAgICAgICAgICAgZnJvbV9zZXJ2ZXIud3JpdGUpCi0gICAgICAgIHNlcnZlci5fc2VydmVfb25l
X3JlcXVlc3QocHJvdG9jb2wpCisgICAgICAgIHNlcnZlci5fc2VydmVfb25lX3JlcXVlc3Qoc21h
cnRfcHJvdG9jb2wpCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJ29rXG4nCiAgICAgICAgICAg
ICAgICAgICAgICAgICAgJzE3XG4nCiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NvbnRlbnRz
XG5vZlxuZmlsZVxuJwpAQCAtNjM2LDcgKzY0MCw4IEBACiAgICAgICAgIHNhbXBsZV9yZXF1ZXN0
X2J5dGVzID0gJ2NvbW1hbmRcbjlcbmJ1bGsgZGF0YWRvbmVcbicKICAgICAgICAgdG9fc2VydmVy
ID0gU3RyaW5nSU8oc2FtcGxlX3JlcXVlc3RfYnl0ZXMpCiAgICAgICAgIGZyb21fc2VydmVyID0g
U3RyaW5nSU8oKQotICAgICAgICBzZXJ2ZXIgPSBzbWFydC5TbWFydFNlcnZlclBpcGVTdHJlYW1N
ZWRpdW0odG9fc2VydmVyLCBmcm9tX3NlcnZlciwgTm9uZSkKKyAgICAgICAgc2VydmVyID0gbWVk
aXVtLlNtYXJ0U2VydmVyUGlwZVN0cmVhbU1lZGl1bSgKKyAgICAgICAgICAgIHRvX3NlcnZlciwg
ZnJvbV9zZXJ2ZXIsIE5vbmUpCiAgICAgICAgIHNhbXBsZV9wcm90b2NvbCA9IFNhbXBsZVJlcXVl
c3QoZXhwZWN0ZWRfYnl0ZXM9c2FtcGxlX3JlcXVlc3RfYnl0ZXMpCiAgICAgICAgIHNlcnZlci5f
c2VydmVfb25lX3JlcXVlc3Qoc2FtcGxlX3Byb3RvY29sKQogICAgICAgICBzZWxmLmFzc2VydEVx
dWFsKCcnLCBmcm9tX3NlcnZlci5nZXR2YWx1ZSgpKQpAQCAtNjQ2LDcgKzY1MSw3IEBACiAgICAg
ZGVmIHRlc3Rfc29ja2V0X3N0cmVhbV93aXRoX2J1bGtfZGF0YShzZWxmKToKICAgICAgICAgc2Ft
cGxlX3JlcXVlc3RfYnl0ZXMgPSAnY29tbWFuZFxuOVxuYnVsayBkYXRhZG9uZVxuJwogICAgICAg
ICBzZXJ2ZXJfc29jaywgY2xpZW50X3NvY2sgPSBzZWxmLnBvcnRhYmxlX3NvY2tldF9wYWlyKCkK
LSAgICAgICAgc2VydmVyID0gc21hcnQuU21hcnRTZXJ2ZXJTb2NrZXRTdHJlYW1NZWRpdW0oCisg
ICAgICAgIHNlcnZlciA9IG1lZGl1bS5TbWFydFNlcnZlclNvY2tldFN0cmVhbU1lZGl1bSgKICAg
ICAgICAgICAgIHNlcnZlcl9zb2NrLCBOb25lKQogICAgICAgICBzYW1wbGVfcHJvdG9jb2wgPSBT
YW1wbGVSZXF1ZXN0KGV4cGVjdGVkX2J5dGVzPXNhbXBsZV9yZXF1ZXN0X2J5dGVzKQogICAgICAg
ICBjbGllbnRfc29jay5zZW5kYWxsKHNhbXBsZV9yZXF1ZXN0X2J5dGVzKQpAQCAtNjU5LDE0ICs2
NjQsMTQgQEAKICAgICBkZWYgdGVzdF9waXBlX2xpa2Vfc3RyZWFtX3NodXRkb3duX2RldGVjdGlv
bihzZWxmKToKICAgICAgICAgdG9fc2VydmVyID0gU3RyaW5nSU8oJycpCiAgICAgICAgIGZyb21f
c2VydmVyID0gU3RyaW5nSU8oKQotICAgICAgICBzZXJ2ZXIgPSBzbWFydC5TbWFydFNlcnZlclBp
cGVTdHJlYW1NZWRpdW0odG9fc2VydmVyLCBmcm9tX3NlcnZlciwgTm9uZSkKKyAgICAgICAgc2Vy
dmVyID0gbWVkaXVtLlNtYXJ0U2VydmVyUGlwZVN0cmVhbU1lZGl1bSh0b19zZXJ2ZXIsIGZyb21f
c2VydmVyLCBOb25lKQogICAgICAgICBzZXJ2ZXIuX3NlcnZlX29uZV9yZXF1ZXN0KFNhbXBsZVJl
cXVlc3QoJ3gnKSkKICAgICAgICAgc2VsZi5hc3NlcnRUcnVlKHNlcnZlci5maW5pc2hlZCkKICAg
ICAgICAgCiAgICAgZGVmIHRlc3Rfc29ja2V0X3N0cmVhbV9zaHV0ZG93bl9kZXRlY3Rpb24oc2Vs
Zik6CiAgICAgICAgIHNlcnZlcl9zb2NrLCBjbGllbnRfc29jayA9IHNlbGYucG9ydGFibGVfc29j
a2V0X3BhaXIoKQogICAgICAgICBjbGllbnRfc29jay5jbG9zZSgpCi0gICAgICAgIHNlcnZlciA9
IHNtYXJ0LlNtYXJ0U2VydmVyU29ja2V0U3RyZWFtTWVkaXVtKAorICAgICAgICBzZXJ2ZXIgPSBt
ZWRpdW0uU21hcnRTZXJ2ZXJTb2NrZXRTdHJlYW1NZWRpdW0oCiAgICAgICAgICAgICBzZXJ2ZXJf
c29jaywgTm9uZSkKICAgICAgICAgc2VydmVyLl9zZXJ2ZV9vbmVfcmVxdWVzdChTYW1wbGVSZXF1
ZXN0KCd4JykpCiAgICAgICAgIHNlbGYuYXNzZXJ0VHJ1ZShzZXJ2ZXIuZmluaXNoZWQpCkBAIC02
NzgsNyArNjgzLDggQEAKICAgICAgICAgc2FtcGxlX3JlcXVlc3RfYnl0ZXMgPSAnY29tbWFuZFxu
JwogICAgICAgICB0b19zZXJ2ZXIgPSBTdHJpbmdJTyhzYW1wbGVfcmVxdWVzdF9ieXRlcyAqIDIp
CiAgICAgICAgIGZyb21fc2VydmVyID0gU3RyaW5nSU8oKQotICAgICAgICBzZXJ2ZXIgPSBzbWFy
dC5TbWFydFNlcnZlclBpcGVTdHJlYW1NZWRpdW0odG9fc2VydmVyLCBmcm9tX3NlcnZlciwgTm9u
ZSkKKyAgICAgICAgc2VydmVyID0gbWVkaXVtLlNtYXJ0U2VydmVyUGlwZVN0cmVhbU1lZGl1bSgK
KyAgICAgICAgICAgIHRvX3NlcnZlciwgZnJvbV9zZXJ2ZXIsIE5vbmUpCiAgICAgICAgIGZpcnN0
X3Byb3RvY29sID0gU2FtcGxlUmVxdWVzdChleHBlY3RlZF9ieXRlcz1zYW1wbGVfcmVxdWVzdF9i
eXRlcykKICAgICAgICAgc2VydmVyLl9zZXJ2ZV9vbmVfcmVxdWVzdChmaXJzdF9wcm90b2NvbCkK
ICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgwLCBmaXJzdF9wcm90b2NvbC5uZXh0X3JlYWRfc2l6
ZSgpKQpAQCAtNjk4LDcgKzcwNCw3IEBACiAgICAgICAgICMgYmVlbiByZWNlaXZlZCBzZXBlcmF0
ZWx5LgogICAgICAgICBzYW1wbGVfcmVxdWVzdF9ieXRlcyA9ICdjb21tYW5kXG4nCiAgICAgICAg
IHNlcnZlcl9zb2NrLCBjbGllbnRfc29jayA9IHNlbGYucG9ydGFibGVfc29ja2V0X3BhaXIoKQot
ICAgICAgICBzZXJ2ZXIgPSBzbWFydC5TbWFydFNlcnZlclNvY2tldFN0cmVhbU1lZGl1bSgKKyAg
ICAgICAgc2VydmVyID0gbWVkaXVtLlNtYXJ0U2VydmVyU29ja2V0U3RyZWFtTWVkaXVtKAogICAg
ICAgICAgICAgc2VydmVyX3NvY2ssIE5vbmUpCiAgICAgICAgIGZpcnN0X3Byb3RvY29sID0gU2Ft
cGxlUmVxdWVzdChleHBlY3RlZF9ieXRlcz1zYW1wbGVfcmVxdWVzdF9ieXRlcykKICAgICAgICAg
IyBQdXQgdHdvIHdob2xlIHJlcXVlc3RzIG9uIHRoZSB3aXJlLgpAQCAtNzI1LDcgKzczMSw4IEBA
CiAgICAgICAgIGRlZiBjbG9zZSgpOgogICAgICAgICAgICAgc2VsZi5jbG9zZWQgPSBUcnVlCiAg
ICAgICAgIGZyb21fc2VydmVyLmNsb3NlID0gY2xvc2UKLSAgICAgICAgc2VydmVyID0gc21hcnQu
U21hcnRTZXJ2ZXJQaXBlU3RyZWFtTWVkaXVtKHRvX3NlcnZlciwgZnJvbV9zZXJ2ZXIsIE5vbmUp
CisgICAgICAgIHNlcnZlciA9IG1lZGl1bS5TbWFydFNlcnZlclBpcGVTdHJlYW1NZWRpdW0oCisg
ICAgICAgICAgICB0b19zZXJ2ZXIsIGZyb21fc2VydmVyLCBOb25lKQogICAgICAgICBmYWtlX3By
b3RvY29sID0gRXJyb3JSYWlzaW5nUHJvdG9jb2woRXhjZXB0aW9uKCdib29tJykpCiAgICAgICAg
IHNlcnZlci5fc2VydmVfb25lX3JlcXVlc3QoZmFrZV9wcm90b2NvbCkKICAgICAgICAgc2VsZi5h
c3NlcnRFcXVhbCgnJywgZnJvbV9zZXJ2ZXIuZ2V0dmFsdWUoKSkKQEAgLTczNyw3ICs3NDQsNyBA
QAogICAgICAgICAjIG5vdCBkaXNjYXJkIHRoZSBjb250ZW50cy4KICAgICAgICAgZnJvbSBTdHJp
bmdJTyBpbXBvcnQgU3RyaW5nSU8KICAgICAgICAgc2VydmVyX3NvY2ssIGNsaWVudF9zb2NrID0g
c2VsZi5wb3J0YWJsZV9zb2NrZXRfcGFpcigpCi0gICAgICAgIHNlcnZlciA9IHNtYXJ0LlNtYXJ0
U2VydmVyU29ja2V0U3RyZWFtTWVkaXVtKAorICAgICAgICBzZXJ2ZXIgPSBtZWRpdW0uU21hcnRT
ZXJ2ZXJTb2NrZXRTdHJlYW1NZWRpdW0oCiAgICAgICAgICAgICBzZXJ2ZXJfc29jaywgTm9uZSkK
ICAgICAgICAgZmFrZV9wcm90b2NvbCA9IEVycm9yUmFpc2luZ1Byb3RvY29sKEV4Y2VwdGlvbign
Ym9vbScpKQogICAgICAgICBzZXJ2ZXIuX3NlcnZlX29uZV9yZXF1ZXN0KGZha2VfcHJvdG9jb2wp
CkBAIC03NTEsNyArNzU4LDggQEAKICAgICAgICAgIyBub3QgZGlzY2FyZCB0aGUgY29udGVudHMu
CiAgICAgICAgIHRvX3NlcnZlciA9IFN0cmluZ0lPKCcnKQogICAgICAgICBmcm9tX3NlcnZlciA9
IFN0cmluZ0lPKCkKLSAgICAgICAgc2VydmVyID0gc21hcnQuU21hcnRTZXJ2ZXJQaXBlU3RyZWFt
TWVkaXVtKHRvX3NlcnZlciwgZnJvbV9zZXJ2ZXIsIE5vbmUpCisgICAgICAgIHNlcnZlciA9IG1l
ZGl1bS5TbWFydFNlcnZlclBpcGVTdHJlYW1NZWRpdW0oCisgICAgICAgICAgICB0b19zZXJ2ZXIs
IGZyb21fc2VydmVyLCBOb25lKQogICAgICAgICBmYWtlX3Byb3RvY29sID0gRXJyb3JSYWlzaW5n
UHJvdG9jb2woS2V5Ym9hcmRJbnRlcnJ1cHQoJ2Jvb20nKSkKICAgICAgICAgc2VsZi5hc3NlcnRS
YWlzZXMoCiAgICAgICAgICAgICBLZXlib2FyZEludGVycnVwdCwgc2VydmVyLl9zZXJ2ZV9vbmVf
cmVxdWVzdCwgZmFrZV9wcm90b2NvbCkKQEAgLTc1OSw3ICs3NjcsNyBAQAogCiAgICAgZGVmIHRl
c3Rfc29ja2V0X3N0cmVhbV9rZXlib2FyZF9pbnRlcnJ1cHRfaGFuZGxpbmcoc2VsZik6CiAgICAg
ICAgIHNlcnZlcl9zb2NrLCBjbGllbnRfc29jayA9IHNlbGYucG9ydGFibGVfc29ja2V0X3BhaXIo
KQotICAgICAgICBzZXJ2ZXIgPSBzbWFydC5TbWFydFNlcnZlclNvY2tldFN0cmVhbU1lZGl1bSgK
KyAgICAgICAgc2VydmVyID0gbWVkaXVtLlNtYXJ0U2VydmVyU29ja2V0U3RyZWFtTWVkaXVtKAog
ICAgICAgICAgICAgc2VydmVyX3NvY2ssIE5vbmUpCiAgICAgICAgIGZha2VfcHJvdG9jb2wgPSBF
cnJvclJhaXNpbmdQcm90b2NvbChLZXlib2FyZEludGVycnVwdCgnYm9vbScpKQogICAgICAgICBz
ZWxmLmFzc2VydFJhaXNlcygKQEAgLTc3OCw3ICs3ODYsNyBAQAogICAgICAgICBzbWFydF9zZXJ2
ZXIgPSBzZXJ2ZXIuU21hcnRUQ1BTZXJ2ZXIoYmFja2luZ190cmFuc3BvcnQ9Rmxha3lUcmFuc3Bv
cnQoKSkKICAgICAgICAgc21hcnRfc2VydmVyLnN0YXJ0X2JhY2tncm91bmRfdGhyZWFkKCkKICAg
ICAgICAgdHJ5OgotICAgICAgICAgICAgdHJhbnNwb3J0ID0gc21hcnQuU21hcnRUQ1BUcmFuc3Bv
cnQoc21hcnRfc2VydmVyLmdldF91cmwoKSkKKyAgICAgICAgICAgIHRyYW5zcG9ydCA9IHJlbW90
ZS5TbWFydFRDUFRyYW5zcG9ydChzbWFydF9zZXJ2ZXIuZ2V0X3VybCgpKQogICAgICAgICAgICAg
dHJ5OgogICAgICAgICAgICAgICAgIHRyYW5zcG9ydC5nZXQoJ3NvbWV0aGluZycpCiAgICAgICAg
ICAgICBleGNlcHQgZXJyb3JzLlRyYW5zcG9ydEVycm9yLCBlOgpAQCAtODA5LDcgKzgxNyw3IEBA
CiAgICAgICAgICAgICBzZWxmLmJhY2tpbmdfdHJhbnNwb3J0ID0gZ2V0X3RyYW5zcG9ydCgicmVh
ZG9ubHkrIiArIHNlbGYuYmFja2luZ190cmFuc3BvcnQuYWJzcGF0aCgnLicpKQogICAgICAgICBz
ZWxmLnNlcnZlciA9IHNlcnZlci5TbWFydFRDUFNlcnZlcihzZWxmLmJhY2tpbmdfdHJhbnNwb3J0
KQogICAgICAgICBzZWxmLnNlcnZlci5zdGFydF9iYWNrZ3JvdW5kX3RocmVhZCgpCi0gICAgICAg
IHNlbGYudHJhbnNwb3J0ID0gc21hcnQuU21hcnRUQ1BUcmFuc3BvcnQoc2VsZi5zZXJ2ZXIuZ2V0
X3VybCgpKQorICAgICAgICBzZWxmLnRyYW5zcG9ydCA9IHJlbW90ZS5TbWFydFRDUFRyYW5zcG9y
dChzZWxmLnNlcnZlci5nZXRfdXJsKCkpCiAKICAgICBkZWYgdGVhckRvd24oc2VsZik6CiAgICAg
ICAgIGlmIGdldGF0dHIoc2VsZiwgJ3RyYW5zcG9ydCcsIE5vbmUpOgpAQCAtOTEwLDExICs5MTgs
MTEgQEAKIAogICAgIGRlZiB0ZXN0X2NvbnN0cnVjdF9yZXF1ZXN0X2hhbmRsZXIoc2VsZik6CiAg
ICAgICAgICIiIkNvbnN0cnVjdGluZyBhIHJlcXVlc3QgaGFuZGxlciBzaG91bGQgYmUgZWFzeSBh
bmQgc2V0IGRlZmF1bHRzLiIiIgotICAgICAgICBoYW5kbGVyID0gc21hcnQuU21hcnRTZXJ2ZXJS
ZXF1ZXN0SGFuZGxlcihOb25lKQorICAgICAgICBoYW5kbGVyID0gcmVxdWVzdC5TbWFydFNlcnZl
clJlcXVlc3RIYW5kbGVyKE5vbmUpCiAgICAgICAgIHNlbGYuYXNzZXJ0RmFsc2UoaGFuZGxlci5m
aW5pc2hlZF9yZWFkaW5nKQogCiAgICAgZGVmIHRlc3RfaGVsbG8oc2VsZik6Ci0gICAgICAgIGhh
bmRsZXIgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKE5vbmUpCisgICAgICAgIGhh
bmRsZXIgPSByZXF1ZXN0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoTm9uZSkKICAgICAgICAg
aGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdoZWxsbycsICgpKQogICAgICAgICBzZWxmLmFzc2Vy
dEVxdWFsKCgnb2snLCAnMScpLCBoYW5kbGVyLnJlc3BvbnNlLmFyZ3MpCiAgICAgICAgIHNlbGYu
YXNzZXJ0RXF1YWwoTm9uZSwgaGFuZGxlci5yZXNwb25zZS5ib2R5KQpAQCAtOTI2LDE0ICs5MzQs
MTQgQEAKICAgICAgICAgd3QuYWRkKCdoZWxsbycpCiAgICAgICAgIHJldl9pZCA9IHd0LmNvbW1p
dCgnYWRkIGhlbGxvJykKICAgICAgICAgCi0gICAgICAgIGhhbmRsZXIgPSBzbWFydC5TbWFydFNl
cnZlclJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3RyYW5zcG9ydCgpKQorICAgICAgICBoYW5kbGVy
ID0gcmVxdWVzdC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3RyYW5zcG9ydCgp
KQogICAgICAgICBoYW5kbGVyLmRpc3BhdGNoX2NvbW1hbmQoJ2dldF9idW5kbGUnLCAoJy4nLCBy
ZXZfaWQpKQogICAgICAgICBidW5kbGUgPSBzZXJpYWxpemVyLnJlYWRfYnVuZGxlKFN0cmluZ0lP
KGhhbmRsZXIucmVzcG9uc2UuYm9keSkpCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoKCksIGhh
bmRsZXIucmVzcG9uc2UuYXJncykKIAogICAgIGRlZiB0ZXN0X3JlYWRvbmx5X2V4Y2VwdGlvbl9i
ZWNvbWVzX3RyYW5zcG9ydF9ub3RfcG9zc2libGUoc2VsZik6CiAgICAgICAgICIiIlRoZSByZXNw
b25zZSBmb3IgYSByZWFkLW9ubHkgZXJyb3IgaXMgKCdSZWFkT25seUVycm9yJykuIiIiCi0gICAg
ICAgIGhhbmRsZXIgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3Jl
YWRvbmx5X3RyYW5zcG9ydCgpKQorICAgICAgICBoYW5kbGVyID0gcmVxdWVzdC5TbWFydFNlcnZl
clJlcXVlc3RIYW5kbGVyKHNlbGYuZ2V0X3JlYWRvbmx5X3RyYW5zcG9ydCgpKQogICAgICAgICAj
IHNlbmQgYSBta2RpciBmb3IgZm9vLCB3aXRoIG5vIGV4cGxpY2l0IG1vZGUgLSBzaG91bGQgZmFp
bC4KICAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdta2RpcicsICgnZm9vJywgJycp
KQogICAgICAgICAjIGFuZCB0aGUgZmFpbHVyZSBzaG91bGQgYmUgYW4gZXhwbGljaXQgUmVhZE9u
bHlFcnJvcgpAQCAtOTQ1LDE0ICs5NTMsMTQgQEAKIAogICAgIGRlZiB0ZXN0X2hlbGxvX2hhc19m
aW5pc2hlZF9ib2R5X29uX2Rpc3BhdGNoKHNlbGYpOgogICAgICAgICAiIiJUaGUgJ2hlbGxvJyBj
b21tYW5kIHNob3VsZCBzZXQgZmluaXNoZWRfcmVhZGluZy4iIiIKLSAgICAgICAgaGFuZGxlciA9
IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoTm9uZSkKKyAgICAgICAgaGFuZGxlciA9
IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihOb25lKQogICAgICAgICBoYW5kbGVy
LmRpc3BhdGNoX2NvbW1hbmQoJ2hlbGxvJywgKCkpCiAgICAgICAgIHNlbGYuYXNzZXJ0VHJ1ZSho
YW5kbGVyLmZpbmlzaGVkX3JlYWRpbmcpCiAgICAgICAgIHNlbGYuYXNzZXJ0Tm90RXF1YWwoTm9u
ZSwgaGFuZGxlci5yZXNwb25zZSkKIAogICAgIGRlZiB0ZXN0X3B1dF9ieXRlc19ub25fYXRvbWlj
KHNlbGYpOgogICAgICAgICAiIiIncHV0Xy4uLicgc2hvdWxkIHNldCBmaW5pc2hlZF9yZWFkaW5n
IGFmdGVyIHJlYWRpbmcgdGhlIGJ5dGVzLiIiIgotICAgICAgICBoYW5kbGVyID0gc21hcnQuU21h
cnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihzZWxmLmdldF90cmFuc3BvcnQoKSkKKyAgICAgICAgaGFu
ZGxlciA9IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihzZWxmLmdldF90cmFuc3Bv
cnQoKSkKICAgICAgICAgaGFuZGxlci5kaXNwYXRjaF9jb21tYW5kKCdwdXRfbm9uX2F0b21pYycs
ICgnYS1maWxlJywgJycsICdGJywgJycpKQogICAgICAgICBzZWxmLmFzc2VydEZhbHNlKGhhbmRs
ZXIuZmluaXNoZWRfcmVhZGluZykKICAgICAgICAgaGFuZGxlci5hY2NlcHRfYm9keSgnMTIzNCcp
CkBAIC05NjYsNyArOTc0LDcgQEAKICAgICBkZWYgdGVzdF9yZWFkdl9hY2NlcHRfYm9keShzZWxm
KToKICAgICAgICAgIiIiJ3JlYWR2JyBzaG91bGQgc2V0IGZpbmlzaGVkX3JlYWRpbmcgYWZ0ZXIg
cmVhZGluZyBvZmZzZXRzLiIiIgogICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoWydhLWZpbGUnXSkK
LSAgICAgICAgaGFuZGxlciA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5n
ZXRfcmVhZG9ubHlfdHJhbnNwb3J0KCkpCisgICAgICAgIGhhbmRsZXIgPSByZXF1ZXN0LlNtYXJ0
U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfcmVhZG9ubHlfdHJhbnNwb3J0KCkpCiAgICAg
ICAgIGhhbmRsZXIuZGlzcGF0Y2hfY29tbWFuZCgncmVhZHYnLCAoJ2EtZmlsZScsICkpCiAgICAg
ICAgIHNlbGYuYXNzZXJ0RmFsc2UoaGFuZGxlci5maW5pc2hlZF9yZWFkaW5nKQogICAgICAgICBo
YW5kbGVyLmFjY2VwdF9ib2R5KCcyLCcpCkBAIC05ODEsNyArOTg5LDcgQEAKICAgICBkZWYgdGVz
dF9yZWFkdl9zaG9ydF9yZWFkX3Jlc3BvbnNlX2NvbnRlbnRzKHNlbGYpOgogICAgICAgICAiIiIn
cmVhZHYnIHdoZW4gYSBzaG9ydCByZWFkIG9jY3VycyBzZXRzIHRoZSByZXNwb25zZSBhcHByb3By
aWF0ZWx5LiIiIgogICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoWydhLWZpbGUnXSkKLSAgICAgICAg
aGFuZGxlciA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoc2VsZi5nZXRfcmVhZG9u
bHlfdHJhbnNwb3J0KCkpCisgICAgICAgIGhhbmRsZXIgPSByZXF1ZXN0LlNtYXJ0U2VydmVyUmVx
dWVzdEhhbmRsZXIoc2VsZi5nZXRfcmVhZG9ubHlfdHJhbnNwb3J0KCkpCiAgICAgICAgIGhhbmRs
ZXIuZGlzcGF0Y2hfY29tbWFuZCgncmVhZHYnLCAoJ2EtZmlsZScsICkpCiAgICAgICAgICMgcmVh
ZCBiZXlvbmQgdGhlIGVuZCBvZiB0aGUgZmlsZS4KICAgICAgICAgaGFuZGxlci5hY2NlcHRfYm9k
eSgnMTAwLDEnKQpAQCAtOTkyLDIyICsxMDAwLDIzIEBACiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1
YWwoTm9uZSwgaGFuZGxlci5yZXNwb25zZS5ib2R5KQogCiAKLWNsYXNzIFNtYXJ0VHJhbnNwb3J0
UmVnaXN0cmF0aW9uKHRlc3RzLlRlc3RDYXNlKToKK2NsYXNzIFJlbW90ZVRyYW5zcG9ydFJlZ2lz
dHJhdGlvbih0ZXN0cy5UZXN0Q2FzZSk6CiAKICAgICBkZWYgdGVzdF9yZWdpc3RyYXRpb24oc2Vs
Zik6CiAgICAgICAgIHQgPSBnZXRfdHJhbnNwb3J0KCdienIrc3NoOi8vZXhhbXBsZS5jb20vcGF0
aCcpCi0gICAgICAgIHNlbGYuYXNzZXJ0SXNJbnN0YW5jZSh0LCBzbWFydC5TbWFydFNTSFRyYW5z
cG9ydCkKKyAgICAgICAgc2VsZi5hc3NlcnRJc0luc3RhbmNlKHQsIHJlbW90ZS5TbWFydFNTSFRy
YW5zcG9ydCkKICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgnZXhhbXBsZS5jb20nLCB0Ll9ob3N0
KQogCiAKLWNsYXNzIFRlc3RTbWFydFRyYW5zcG9ydCh0ZXN0cy5UZXN0Q2FzZSk6CitjbGFzcyBU
ZXN0UmVtb3RlVHJhbnNwb3J0KHRlc3RzLlRlc3RDYXNlKToKICAgICAgICAgCiAgICAgZGVmIHRl
c3RfdXNlX2Nvbm5lY3Rpb25fZmFjdG9yeShzZWxmKToKLSAgICAgICAgIyBXZSB3YW50IHRvIGJl
IGFibGUgdG8gcGFzcyBhIGNsaWVudCBhcyBhIHBhcmFtZXRlciB0byBTbWFydFRyYW5zcG9ydC4K
KyAgICAgICAgIyBXZSB3YW50IHRvIGJlIGFibGUgdG8gcGFzcyBhIGNsaWVudCBhcyBhIHBhcmFt
ZXRlciB0byBSZW1vdGVUcmFuc3BvcnQuCiAgICAgICAgIGlucHV0ID0gU3RyaW5nSU8oIm9rXG4z
XG5iYXJkb25lXG4iKQogICAgICAgICBvdXRwdXQgPSBTdHJpbmdJTygpCi0gICAgICAgIG1lZGl1
bSA9IHNtYXJ0LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKLSAg
ICAgICAgdHJhbnNwb3J0ID0gc21hcnQuU21hcnRUcmFuc3BvcnQoJ2J6cjovL2xvY2FsaG9zdC8n
LCBtZWRpdW09bWVkaXVtKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U2lt
cGxlUGlwZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKKyAgICAgICAgdHJhbnNwb3J0ID0g
cmVtb3RlLlNtYXJ0VHJhbnNwb3J0KAorICAgICAgICAgICAgJ2J6cjovL2xvY2FsaG9zdC8nLCBt
ZWRpdW09Y2xpZW50X21lZGl1bSkKIAogICAgICAgICAjIFdlIHdhbnQgdG8gbWFrZSBzdXJlIHRo
ZSBjbGllbnQgaXMgdXNlZCB3aGVuIHRoZSBmaXJzdCByZW1vdGUKICAgICAgICAgIyBtZXRob2Qg
aXMgY2FsbGVkLiAgTm8gZGF0YSBzaG91bGQgaGF2ZSBiZWVuIHNlbnQsIG9yIHJlYWQuCkBAIC0x
MDI1LDE3ICsxMDM0LDE4IEBACiAKICAgICBkZWYgdGVzdF9fdHJhbnNsYXRlX2Vycm9yX3JlYWRv
bmx5KHNlbGYpOgogICAgICAgICAiIiJTZW5kaW5nIGEgUmVhZE9ubHlFcnJvciB0byBfdHJhbnNs
YXRlX2Vycm9yIHJhaXNlcyBUcmFuc3BvcnROb3RQb3NzaWJsZS4iIiIKLSAgICAgICAgbWVkaXVt
ID0gc21hcnQuU21hcnRDbGllbnRNZWRpdW0oKQotICAgICAgICB0cmFuc3BvcnQgPSBzbWFydC5T
bWFydFRyYW5zcG9ydCgnYnpyOi8vbG9jYWxob3N0LycsIG1lZGl1bT1tZWRpdW0pCisgICAgICAg
IGNsaWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRDbGllbnRNZWRpdW0oKQorICAgICAgICB0cmFu
c3BvcnQgPSByZW1vdGUuU21hcnRUcmFuc3BvcnQoCisgICAgICAgICAgICAnYnpyOi8vbG9jYWxo
b3N0LycsIG1lZGl1bT1jbGllbnRfbWVkaXVtKQogICAgICAgICBzZWxmLmFzc2VydFJhaXNlcyhl
cnJvcnMuVHJhbnNwb3J0Tm90UG9zc2libGUsCiAgICAgICAgICAgICB0cmFuc3BvcnQuX3RyYW5z
bGF0ZV9lcnJvciwgKCJSZWFkT25seUVycm9yIiwgKSkKIAogCi1jbGFzcyBJbnN0cnVtZW50ZWRT
ZXJ2ZXJQcm90b2NvbChzbWFydC5TbWFydFNlcnZlclN0cmVhbU1lZGl1bSk6CitjbGFzcyBJbnN0
cnVtZW50ZWRTZXJ2ZXJQcm90b2NvbChtZWRpdW0uU21hcnRTZXJ2ZXJTdHJlYW1NZWRpdW0pOgog
ICAgICIiIkEgc21hcnQgc2VydmVyIHdoaWNoIGlzIGJhY2tlZCBieSBtZW1vcnkgYW5kIHNhdmVz
IGl0cyB3cml0ZSByZXF1ZXN0cy4iIiIKIAogICAgIGRlZiBfX2luaXRfXyhzZWxmLCB3cml0ZV9v
dXRwdXRfbGlzdCk6Ci0gICAgICAgIHNtYXJ0LlNtYXJ0U2VydmVyU3RyZWFtTWVkaXVtLl9faW5p
dF9fKHNlbGYsIG1lbW9yeS5NZW1vcnlUcmFuc3BvcnQoKSkKKyAgICAgICAgbWVkaXVtLlNtYXJ0
U2VydmVyU3RyZWFtTWVkaXVtLl9faW5pdF9fKHNlbGYsIG1lbW9yeS5NZW1vcnlUcmFuc3BvcnQo
KSkKICAgICAgICAgc2VsZi5fd3JpdGVfb3V0cHV0X2xpc3QgPSB3cml0ZV9vdXRwdXRfbGlzdAog
CiAKQEAgLTEwNTQsMTUgKzEwNjQsMTkgQEAKIAogICAgIGRlZiBzZXRVcChzZWxmKToKICAgICAg
ICAgc3VwZXIoVGVzdFNtYXJ0UHJvdG9jb2wsIHNlbGYpLnNldFVwKCkKKyAgICAgICAgIyBYWFg6
IHNlbGYuc2VydmVyX3RvX2NsaWVudCBkb2Vzbid0IHNlZW0gdG8gYmUgdXNlZC4gIElmIHNvLAor
ICAgICAgICAjIEluc3RydW1lbnRlZFNlcnZlclByb3RvY29sIGlzIHJlZHVuZGFudCB0b28uCiAg
ICAgICAgIHNlbGYuc2VydmVyX3RvX2NsaWVudCA9IFtdCiAgICAgICAgIHNlbGYudG9fc2VydmVy
ID0gU3RyaW5nSU8oKQogICAgICAgICBzZWxmLnRvX2NsaWVudCA9IFN0cmluZ0lPKCkKLSAgICAg
ICAgc2VsZi5jbGllbnRfbWVkaXVtID0gc21hcnQuU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1
bShzZWxmLnRvX2NsaWVudCwKKyAgICAgICAgc2VsZi5jbGllbnRfbWVkaXVtID0gbWVkaXVtLlNt
YXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oc2VsZi50b19jbGllbnQsCiAgICAgICAgICAgICBz
ZWxmLnRvX3NlcnZlcikKLSAgICAgICAgc2VsZi5jbGllbnRfcHJvdG9jb2wgPSBzbWFydC5TbWFy
dENsaWVudFJlcXVlc3RQcm90b2NvbE9uZSgKKyAgICAgICAgc2VsZi5jbGllbnRfcHJvdG9jb2wg
PSBwcm90b2NvbC5TbWFydENsaWVudFJlcXVlc3RQcm90b2NvbE9uZSgKICAgICAgICAgICAgIHNl
bGYuY2xpZW50X21lZGl1bSkKICAgICAgICAgc2VsZi5zbWFydF9zZXJ2ZXIgPSBJbnN0cnVtZW50
ZWRTZXJ2ZXJQcm90b2NvbChzZWxmLnNlcnZlcl90b19jbGllbnQpCi0gICAgICAgIHNlbGYuc21h
cnRfc2VydmVyX3JlcXVlc3QgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKE5vbmUp
CisgICAgICAgIHNlbGYuc21hcnRfc2VydmVyX3JlcXVlc3QgPSByZXF1ZXN0LlNtYXJ0U2VydmVy
UmVxdWVzdEhhbmRsZXIoTm9uZSkKKyMgICAgICAgIHNlbGYuc21hcnRfc2VydmVyX3JlcXVlc3Qg
PSByZXF1ZXN0LlNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIoCisjICAgICAgICAgICAgTm9uZSwg
cmVxdWVzdC5yZXF1ZXN0X2hhbmRsZXJzKQogCiAgICAgZGVmIGFzc2VydE9mZnNldFNlcmlhbGlz
YXRpb24oc2VsZiwgZXhwZWN0ZWRfb2Zmc2V0cywgZXhwZWN0ZWRfc2VyaWFsaXNlZCwKICAgICAg
ICAgY2xpZW50LCBzbWFydF9zZXJ2ZXJfcmVxdWVzdCk6CkBAIC0xMDg0LDM1ICsxMDk4LDM1IEBA
CiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoZXhwZWN0ZWRfc2VyaWFsaXNlZCwgc2VyaWFsaXNl
ZCkKIAogICAgIGRlZiBidWlsZF9wcm90b2NvbF93YWl0aW5nX2Zvcl9ib2R5KHNlbGYpOgotICAg
ICAgICBvdXRfc3RyZWFtID0gU3RyaW5nSU8oKQotICAgICAgICBwcm90b2NvbCA9IHNtYXJ0LlNt
YXJ0U2VydmVyUmVxdWVzdFByb3RvY29sT25lKE5vbmUsIG91dF9zdHJlYW0ud3JpdGUpCi0gICAg
ICAgIHByb3RvY29sLmhhc19kaXNwYXRjaGVkID0gVHJ1ZQotICAgICAgICBwcm90b2NvbC5yZXF1
ZXN0ID0gc21hcnQuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihOb25lKQotICAgICAgICBkZWYg
aGFuZGxlX2VuZF9vZl9ieXRlcygpOgotICAgICAgICAgICAgc2VsZi5lbmRfcmVjZWl2ZWQgPSBU
cnVlCi0gICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdhYmNkZWZnJywgcHJvdG9jb2wucmVx
dWVzdC5fYm9keV9ieXRlcykKLSAgICAgICAgICAgIHByb3RvY29sLnJlcXVlc3QucmVzcG9uc2Ug
PSBzbWFydC5TbWFydFNlcnZlclJlc3BvbnNlKCgnb2snLCApKQotICAgICAgICBwcm90b2NvbC5y
ZXF1ZXN0Ll9lbmRfb2ZfYm9keV9oYW5kbGVyID0gaGFuZGxlX2VuZF9vZl9ieXRlcwotICAgICAg
ICAjIENhbGwgYWNjZXB0X2J5dGVzIHRvIG1ha2Ugc3VyZSB0aGF0IGludGVybmFsIHN0YXRlIGxp
a2UgX2JvZHlfZGVjb2RlcgotICAgICAgICAjIGlzIGluaXRpYWxpc2VkLiAgVGhpcyB0ZXN0IHNo
b3VsZCBwcm9iYWJseSBiZSBnaXZlbiBhIGNsZWFyZXIKLSAgICAgICAgIyBpbnRlcmZhY2UgdG8g
d29yayB3aXRoIHRoYXQgd2lsbCBub3QgY2F1c2UgdGhpcyBpbmNvbnNpc3RlbmN5LgotICAgICAg
ICAjICAgLS0gQW5kcmV3IEJlbm5ldHRzLCAyMDA2LTA5LTI4Ci0gICAgICAgIHByb3RvY29sLmFj
Y2VwdF9ieXRlcygnJykKLSAgICAgICAgcmV0dXJuIHByb3RvY29sCisgICAgICAgb3V0X3N0cmVh
bSA9IFN0cmluZ0lPKCkKKyAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3RvY29sLlNtYXJ0U2Vy
dmVyUmVxdWVzdFByb3RvY29sT25lKE5vbmUsIG91dF9zdHJlYW0ud3JpdGUpCisgICAgICAgc21h
cnRfcHJvdG9jb2wuaGFzX2Rpc3BhdGNoZWQgPSBUcnVlCisgICAgICAgc21hcnRfcHJvdG9jb2wu
cmVxdWVzdCA9IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXF1ZXN0SGFuZGxlcihOb25lKQorICAgICAg
IGRlZiBoYW5kbGVfZW5kX29mX2J5dGVzKCk6CisgICAgICAgICAgIHNlbGYuZW5kX3JlY2VpdmVk
ID0gVHJ1ZQorICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdhYmNkZWZnJywgc21hcnRfcHJv
dG9jb2wucmVxdWVzdC5fYm9keV9ieXRlcykKKyAgICAgICAgICAgc21hcnRfcHJvdG9jb2wucmVx
dWVzdC5yZXNwb25zZSA9IHJlcXVlc3QuU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ29rJywgKSkKKyAg
ICAgICBzbWFydF9wcm90b2NvbC5yZXF1ZXN0Ll9lbmRfb2ZfYm9keV9oYW5kbGVyID0gaGFuZGxl
X2VuZF9vZl9ieXRlcworICAgICAgICMgQ2FsbCBhY2NlcHRfYnl0ZXMgdG8gbWFrZSBzdXJlIHRo
YXQgaW50ZXJuYWwgc3RhdGUgbGlrZSBfYm9keV9kZWNvZGVyCisgICAgICAgIyBpcyBpbml0aWFs
aXNlZC4gIFRoaXMgdGVzdCBzaG91bGQgcHJvYmFibHkgYmUgZ2l2ZW4gYSBjbGVhcmVyCisgICAg
ICAgIyBpbnRlcmZhY2UgdG8gd29yayB3aXRoIHRoYXQgd2lsbCBub3QgY2F1c2UgdGhpcyBpbmNv
bnNpc3RlbmN5LgorICAgICAgICMgICAtLSBBbmRyZXcgQmVubmV0dHMsIDIwMDYtMDktMjgKKyAg
ICAgICBzbWFydF9wcm90b2NvbC5hY2NlcHRfYnl0ZXMoJycpCisgICAgICAgcmV0dXJuIHNtYXJ0
X3Byb3RvY29sCiAKICAgICBkZWYgdGVzdF9jb25zdHJ1Y3RfdmVyc2lvbl9vbmVfc2VydmVyX3By
b3RvY29sKHNlbGYpOgotICAgICAgICBwcm90b2NvbCA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVz
dFByb3RvY29sT25lKE5vbmUsIE5vbmUpCi0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJycsIHBy
b3RvY29sLmV4Y2Vzc19idWZmZXIpCi0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJycsIHByb3Rv
Y29sLmluX2J1ZmZlcikKLSAgICAgICAgc2VsZi5hc3NlcnRGYWxzZShwcm90b2NvbC5oYXNfZGlz
cGF0Y2hlZCkKLSAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgxLCBwcm90b2NvbC5uZXh0X3JlYWRf
c2l6ZSgpKQorICAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3RvY29sLlNtYXJ0U2VydmVyUmVx
dWVzdFByb3RvY29sT25lKE5vbmUsIE5vbmUpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJycs
IHNtYXJ0X3Byb3RvY29sLmV4Y2Vzc19idWZmZXIpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwo
JycsIHNtYXJ0X3Byb3RvY29sLmluX2J1ZmZlcikKKyAgICAgICAgc2VsZi5hc3NlcnRGYWxzZShz
bWFydF9wcm90b2NvbC5oYXNfZGlzcGF0Y2hlZCkKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgx
LCBzbWFydF9wcm90b2NvbC5uZXh0X3JlYWRfc2l6ZSgpKQogCiAgICAgZGVmIHRlc3RfY29uc3Ry
dWN0X3ZlcnNpb25fb25lX2NsaWVudF9wcm90b2NvbChzZWxmKToKICAgICAgICAgIyB3ZSBjYW4g
Y29uc3RydWN0IGEgY2xpZW50IHByb3RvY29sIGZyb20gYSBjbGllbnQgbWVkaXVtIHJlcXVlc3QK
ICAgICAgICAgb3V0cHV0ID0gU3RyaW5nSU8oKQotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFy
dFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKE5vbmUsIG91dHB1dCkKLSAgICAgICAgcmVxdWVzdCA9
IG1lZGl1bS5nZXRfcmVxdWVzdCgpCi0gICAgICAgIGNsaWVudF9wcm90b2NvbCA9IHNtYXJ0LlNt
YXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKHJlcXVlc3QpCisgICAgICAgIGNsaWVudF9tZWRp
dW0gPSBtZWRpdW0uU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShOb25lLCBvdXRwdXQpCisg
ICAgICAgIHJlcXVlc3QgPSBjbGllbnRfbWVkaXVtLmdldF9yZXF1ZXN0KCkKKyAgICAgICAgY2xp
ZW50X3Byb3RvY29sID0gcHJvdG9jb2wuU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9jb2xPbmUocmVx
dWVzdCkKIAogICAgIGRlZiB0ZXN0X3NlcnZlcl9vZmZzZXRfc2VyaWFsaXNhdGlvbihzZWxmKToK
ICAgICAgICAgIiIiVGhlIFNtYXJ0IHByb3RvY29sIHNlcmlhbGlzZXMgb2Zmc2V0cyBhcyBhIGNv
bW1hIGFuZCBcbiBzdHJpbmcuCkBAIC0xMTMyLDE0ICsxMTQ2LDE2IEBACiAKICAgICBkZWYgdGVz
dF9hY2NlcHRfYnl0ZXNfb2ZfYmFkX3JlcXVlc3RfdG9fcHJvdG9jb2woc2VsZik6CiAgICAgICAg
IG91dF9zdHJlYW0gPSBTdHJpbmdJTygpCi0gICAgICAgIHByb3RvY29sID0gc21hcnQuU21hcnRT
ZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoTm9uZSwgb3V0X3N0cmVhbS53cml0ZSkKLSAgICAgICAg
cHJvdG9jb2wuYWNjZXB0X2J5dGVzKCdhYmMnKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdh
YmMnLCBwcm90b2NvbC5pbl9idWZmZXIpCi0gICAgICAgIHByb3RvY29sLmFjY2VwdF9ieXRlcygn
XG4nKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCJlcnJvclx4MDFHZW5lcmljIGJ6ciBzbWFy
dCBwcm90b2NvbCBlcnJvcjogYmFkIHJlcXVlc3QiCi0gICAgICAgICAgICAiICdhYmMnXG4iLCBv
dXRfc3RyZWFtLmdldHZhbHVlKCkpCi0gICAgICAgIHNlbGYuYXNzZXJ0VHJ1ZShwcm90b2NvbC5o
YXNfZGlzcGF0Y2hlZCkKLSAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgwLCBwcm90b2NvbC5uZXh0
X3JlYWRfc2l6ZSgpKQorICAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3RvY29sLlNtYXJ0U2Vy
dmVyUmVxdWVzdFByb3RvY29sT25lKAorICAgICAgICAgICAgTm9uZSwgb3V0X3N0cmVhbS53cml0
ZSkKKyAgICAgICAgc21hcnRfcHJvdG9jb2wuYWNjZXB0X2J5dGVzKCdhYmMnKQorICAgICAgICBz
ZWxmLmFzc2VydEVxdWFsKCdhYmMnLCBzbWFydF9wcm90b2NvbC5pbl9idWZmZXIpCisgICAgICAg
IHNtYXJ0X3Byb3RvY29sLmFjY2VwdF9ieXRlcygnXG4nKQorICAgICAgICBzZWxmLmFzc2VydEVx
dWFsKAorICAgICAgICAgICAgImVycm9yXHgwMUdlbmVyaWMgYnpyIHNtYXJ0IHByb3RvY29sIGVy
cm9yOiBiYWQgcmVxdWVzdCAnYWJjJ1xuIiwKKyAgICAgICAgICAgIG91dF9zdHJlYW0uZ2V0dmFs
dWUoKSkKKyAgICAgICAgc2VsZi5hc3NlcnRUcnVlKHNtYXJ0X3Byb3RvY29sLmhhc19kaXNwYXRj
aGVkKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKDAsIHNtYXJ0X3Byb3RvY29sLm5leHRfcmVh
ZF9zaXplKCkpCiAKICAgICBkZWYgdGVzdF9hY2NlcHRfYm9keV9ieXRlc190b19wcm90b2NvbChz
ZWxmKToKICAgICAgICAgcHJvdG9jb2wgPSBzZWxmLmJ1aWxkX3Byb3RvY29sX3dhaXRpbmdfZm9y
X2JvZHkoKQpAQCAtMTE1MiwyNCArMTE2OCwyNiBAQAogICAgICAgICBzZWxmLmFzc2VydFRydWUo
c2VsZi5lbmRfcmVjZWl2ZWQpCiAKICAgICBkZWYgdGVzdF9hY2NlcHRfcmVxdWVzdF9hbmRfYm9k
eV9hbGxfYXRfb25jZShzZWxmKToKKyAgICAgICAgc2VsZi5fY2FwdHVyZVZhcignTk9fU01BUlRf
VkZTJywgTm9uZSkKICAgICAgICAgbWVtX3RyYW5zcG9ydCA9IG1lbW9yeS5NZW1vcnlUcmFuc3Bv
cnQoKQogICAgICAgICBtZW1fdHJhbnNwb3J0LnB1dF9ieXRlcygnZm9vJywgJ2FiY2RlZmdoaWon
KQogICAgICAgICBvdXRfc3RyZWFtID0gU3RyaW5nSU8oKQotICAgICAgICBwcm90b2NvbCA9IHNt
YXJ0LlNtYXJ0U2VydmVyUmVxdWVzdFByb3RvY29sT25lKG1lbV90cmFuc3BvcnQsCisgICAgICAg
IHNtYXJ0X3Byb3RvY29sID0gcHJvdG9jb2wuU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUo
bWVtX3RyYW5zcG9ydCwKICAgICAgICAgICAgICAgICBvdXRfc3RyZWFtLndyaXRlKQotICAgICAg
ICBwcm90b2NvbC5hY2NlcHRfYnl0ZXMoJ3JlYWR2XHgwMWZvb1xuM1xuMywzZG9uZVxuJykKLSAg
ICAgICAgc2VsZi5hc3NlcnRFcXVhbCgwLCBwcm90b2NvbC5uZXh0X3JlYWRfc2l6ZSgpKQorICAg
ICAgICBzbWFydF9wcm90b2NvbC5hY2NlcHRfYnl0ZXMoJ3JlYWR2XHgwMWZvb1xuM1xuMywzZG9u
ZVxuJykKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgwLCBzbWFydF9wcm90b2NvbC5uZXh0X3Jl
YWRfc2l6ZSgpKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdyZWFkdlxuM1xuZGVmZG9uZVxu
Jywgb3V0X3N0cmVhbS5nZXR2YWx1ZSgpKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCcnLCBw
cm90b2NvbC5leGNlc3NfYnVmZmVyKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCcnLCBwcm90
b2NvbC5pbl9idWZmZXIpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJycsIHNtYXJ0X3Byb3Rv
Y29sLmV4Y2Vzc19idWZmZXIpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoJycsIHNtYXJ0X3By
b3RvY29sLmluX2J1ZmZlcikKIAogICAgIGRlZiB0ZXN0X2FjY2VwdF9leGNlc3NfYnl0ZXNfYXJl
X3ByZXNlcnZlZChzZWxmKToKICAgICAgICAgb3V0X3N0cmVhbSA9IFN0cmluZ0lPKCkKLSAgICAg
ICAgcHJvdG9jb2wgPSBzbWFydC5TbWFydFNlcnZlclJlcXVlc3RQcm90b2NvbE9uZShOb25lLCBv
dXRfc3RyZWFtLndyaXRlKQotICAgICAgICBwcm90b2NvbC5hY2NlcHRfYnl0ZXMoJ2hlbGxvXG5o
ZWxsb1xuJykKKyAgICAgICAgc21hcnRfcHJvdG9jb2wgPSBwcm90b2NvbC5TbWFydFNlcnZlclJl
cXVlc3RQcm90b2NvbE9uZSgKKyAgICAgICAgICAgIE5vbmUsIG91dF9zdHJlYW0ud3JpdGUpCisg
ICAgICAgIHNtYXJ0X3Byb3RvY29sLmFjY2VwdF9ieXRlcygnaGVsbG9cbmhlbGxvXG4nKQogICAg
ICAgICBzZWxmLmFzc2VydEVxdWFsKCJva1x4MDExXG4iLCBvdXRfc3RyZWFtLmdldHZhbHVlKCkp
Ci0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoImhlbGxvXG4iLCBwcm90b2NvbC5leGNlc3NfYnVm
ZmVyKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCIiLCBwcm90b2NvbC5pbl9idWZmZXIpCisg
ICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoImhlbGxvXG4iLCBzbWFydF9wcm90b2NvbC5leGNlc3Nf
YnVmZmVyKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCIiLCBzbWFydF9wcm90b2NvbC5pbl9i
dWZmZXIpCiAKICAgICBkZWYgdGVzdF9hY2NlcHRfZXhjZXNzX2J5dGVzX2FmdGVyX2JvZHkoc2Vs
Zik6CiAgICAgICAgIHByb3RvY29sID0gc2VsZi5idWlsZF9wcm90b2NvbF93YWl0aW5nX2Zvcl9i
b2R5KCkKQEAgLTExODMsMjAgKzEyMDEsMjIgQEAKIAogICAgIGRlZiB0ZXN0X2FjY2VwdF9leGNl
c3NfYnl0ZXNfYWZ0ZXJfZGlzcGF0Y2goc2VsZik6CiAgICAgICAgIG91dF9zdHJlYW0gPSBTdHJp
bmdJTygpCi0gICAgICAgIHByb3RvY29sID0gc21hcnQuU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9j
b2xPbmUoTm9uZSwgb3V0X3N0cmVhbS53cml0ZSkKLSAgICAgICAgcHJvdG9jb2wuYWNjZXB0X2J5
dGVzKCdoZWxsb1xuJykKKyAgICAgICAgc21hcnRfcHJvdG9jb2wgPSBwcm90b2NvbC5TbWFydFNl
cnZlclJlcXVlc3RQcm90b2NvbE9uZSgKKyAgICAgICAgICAgIE5vbmUsIG91dF9zdHJlYW0ud3Jp
dGUpCisgICAgICAgIHNtYXJ0X3Byb3RvY29sLmFjY2VwdF9ieXRlcygnaGVsbG9cbicpCiAgICAg
ICAgIHNlbGYuYXNzZXJ0RXF1YWwoIm9rXHgwMTFcbiIsIG91dF9zdHJlYW0uZ2V0dmFsdWUoKSkK
LSAgICAgICAgcHJvdG9jb2wuYWNjZXB0X2J5dGVzKCdoZWwnKQotICAgICAgICBzZWxmLmFzc2Vy
dEVxdWFsKCJoZWwiLCBwcm90b2NvbC5leGNlc3NfYnVmZmVyKQotICAgICAgICBwcm90b2NvbC5h
Y2NlcHRfYnl0ZXMoJ2xvXG4nKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCJoZWxsb1xuIiwg
cHJvdG9jb2wuZXhjZXNzX2J1ZmZlcikKLSAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgiIiwgcHJv
dG9jb2wuaW5fYnVmZmVyKQorICAgICAgICBzbWFydF9wcm90b2NvbC5hY2NlcHRfYnl0ZXMoJ2hl
bCcpCisgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoImhlbCIsIHNtYXJ0X3Byb3RvY29sLmV4Y2Vz
c19idWZmZXIpCisgICAgICAgIHNtYXJ0X3Byb3RvY29sLmFjY2VwdF9ieXRlcygnbG9cbicpCisg
ICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoImhlbGxvXG4iLCBzbWFydF9wcm90b2NvbC5leGNlc3Nf
YnVmZmVyKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCIiLCBzbWFydF9wcm90b2NvbC5pbl9i
dWZmZXIpCiAKICAgICBkZWYgdGVzdF9fc2VuZF9yZXNwb25zZV9zZXRzX2ZpbmlzaGVkX3JlYWRp
bmcoc2VsZik6Ci0gICAgICAgIHByb3RvY29sID0gc21hcnQuU21hcnRTZXJ2ZXJSZXF1ZXN0UHJv
dG9jb2xPbmUoTm9uZSwgbGFtYmRhIHg6IE5vbmUpCi0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwo
MSwgcHJvdG9jb2wubmV4dF9yZWFkX3NpemUoKSkKLSAgICAgICAgcHJvdG9jb2wuX3NlbmRfcmVz
cG9uc2UoKCd4JywpKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKDAsIHByb3RvY29sLm5leHRf
cmVhZF9zaXplKCkpCisgICAgICAgIHNtYXJ0X3Byb3RvY29sID0gcHJvdG9jb2wuU21hcnRTZXJ2
ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoCisgICAgICAgICAgICBOb25lLCBsYW1iZGEgeDogTm9uZSkK
KyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgxLCBzbWFydF9wcm90b2NvbC5uZXh0X3JlYWRfc2l6
ZSgpKQorICAgICAgICBzbWFydF9wcm90b2NvbC5fc2VuZF9yZXNwb25zZSgoJ3gnLCkpCisgICAg
ICAgIHNlbGYuYXNzZXJ0RXF1YWwoMCwgc21hcnRfcHJvdG9jb2wubmV4dF9yZWFkX3NpemUoKSkK
IAogICAgIGRlZiB0ZXN0X3F1ZXJ5X3ZlcnNpb24oc2VsZik6CiAgICAgICAgICIiInF1ZXJ5X3Zl
cnNpb24gb24gYSBTbWFydENsaWVudFByb3RvY29sT25lIHNob3VsZCByZXR1cm4gYSBudW1iZXIu
CkBAIC0xMjEwLDkgKzEyMzAsMTAgQEAKICAgICAgICAgIyB0aGUgZXJyb3IgaWYgdGhlIHJlc3Bv
bnNlIGlzIGEgbm9uLXVuZGVyc3Rvb2QgdmVyc2lvbi4KICAgICAgICAgaW5wdXQgPSBTdHJpbmdJ
Tygnb2tceDAxMVxuJykKICAgICAgICAgb3V0cHV0ID0gU3RyaW5nSU8oKQotICAgICAgICBtZWRp
dW0gPSBzbWFydC5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCi0g
ICAgICAgIHByb3RvY29sID0gc21hcnQuU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9jb2xPbmUobWVk
aXVtLmdldF9yZXF1ZXN0KCkpCi0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoMSwgcHJvdG9jb2wu
cXVlcnlfdmVyc2lvbigpKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U2lt
cGxlUGlwZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKKyAgICAgICAgcmVxdWVzdCA9IGNs
aWVudF9tZWRpdW0uZ2V0X3JlcXVlc3QoKQorICAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3Rv
Y29sLlNtYXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKHJlcXVlc3QpCisgICAgICAgIHNlbGYu
YXNzZXJ0RXF1YWwoMSwgc21hcnRfcHJvdG9jb2wucXVlcnlfdmVyc2lvbigpKQogCiAgICAgZGVm
IGFzc2VydFNlcnZlclRvQ2xpZW50RW5jb2Rpbmcoc2VsZiwgZXhwZWN0ZWRfYnl0ZXMsIGV4cGVj
dGVkX3R1cGxlLAogICAgICAgICAgICAgaW5wdXRfdHVwbGVzKToKQEAgLTEyMjMsMTcgKzEyNDQs
MTggQEAKICAgICAgICAgIyBleHBlY3RlZCBieXRlcwogICAgICAgICBmb3IgaW5wdXRfdHVwbGUg
aW4gaW5wdXRfdHVwbGVzOgogICAgICAgICAgICAgc2VydmVyX291dHB1dCA9IFN0cmluZ0lPKCkK
LSAgICAgICAgICAgIHNlcnZlcl9wcm90b2NvbCA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdFBy
b3RvY29sT25lKAorICAgICAgICAgICAgc2VydmVyX3Byb3RvY29sID0gcHJvdG9jb2wuU21hcnRT
ZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoCiAgICAgICAgICAgICAgICAgTm9uZSwgc2VydmVyX291
dHB1dC53cml0ZSkKICAgICAgICAgICAgIHNlcnZlcl9wcm90b2NvbC5fc2VuZF9yZXNwb25zZShp
bnB1dF90dXBsZSkKICAgICAgICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoZXhwZWN0ZWRfYnl0ZXMs
IHNlcnZlcl9vdXRwdXQuZ2V0dmFsdWUoKSkKLSAgICAgICAgIyBjaGVjayB0aGUgZGVjb2Rpbmcg
b2YgdGhlIGNsaWVudCBwcm90b2NvbCBmcm9tIGV4cGVjdGVkX2J5dGVzOgorICAgICAgICAjIGNo
ZWNrIHRoZSBkZWNvZGluZyBvZiB0aGUgY2xpZW50IHNtYXJ0X3Byb3RvY29sIGZyb20gZXhwZWN0
ZWRfYnl0ZXM6CiAgICAgICAgIGlucHV0ID0gU3RyaW5nSU8oZXhwZWN0ZWRfYnl0ZXMpCiAgICAg
ICAgIG91dHB1dCA9IFN0cmluZ0lPKCkKLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRTaW1w
bGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwgb3V0cHV0KQotICAgICAgICBwcm90b2NvbCA9IHNt
YXJ0LlNtYXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKG1lZGl1bS5nZXRfcmVxdWVzdCgpKQot
ICAgICAgICBwcm90b2NvbC5jYWxsKCdmb28nKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGV4
cGVjdGVkX3R1cGxlLCBwcm90b2NvbC5yZWFkX3Jlc3BvbnNlX3R1cGxlKCkpCisgICAgICAgIGNs
aWVudF9tZWRpdW0gPSBtZWRpdW0uU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwg
b3V0cHV0KQorICAgICAgICByZXF1ZXN0ID0gY2xpZW50X21lZGl1bS5nZXRfcmVxdWVzdCgpCisg
ICAgICAgIHNtYXJ0X3Byb3RvY29sID0gcHJvdG9jb2wuU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9j
b2xPbmUocmVxdWVzdCkKKyAgICAgICAgc21hcnRfcHJvdG9jb2wuY2FsbCgnZm9vJykKKyAgICAg
ICAgc2VsZi5hc3NlcnRFcXVhbChleHBlY3RlZF90dXBsZSwgc21hcnRfcHJvdG9jb2wucmVhZF9y
ZXNwb25zZV90dXBsZSgpKQogCiAgICAgZGVmIHRlc3RfY2xpZW50X2NhbGxfZW1wdHlfcmVzcG9u
c2Uoc2VsZik6CiAgICAgICAgICMgcHJvdG9jb2wuY2FsbCgpIGNhbiBnZXQgYmFjayBhbiBlbXB0
eSB0dXBsZSBhcyBhIHJlc3BvbnNlLiBUaGlzIG9jY3VycwpAQCAtMTI0OCwxNCArMTI3MCwxNSBA
QAogICAgICAgICAgICAgWygnYScsICdiJywgJzM0JyldKQogCiAgICAgZGVmIHRlc3RfY2xpZW50
X2NhbGxfd2l0aF9ib2R5X2J5dGVzX3VwbG9hZHMoc2VsZik6Ci0gICAgICAgICMgcHJvdG9jb2wu
Y2FsbF93aXRoX3VwbG9hZCBzaG91bGQgbGVuZ3RoLXByZWZpeCB0aGUgYnl0ZXMgb250byB0aGUg
CisgICAgICAgICMgcHJvdG9jb2wuY2FsbF93aXRoX2JvZHlfYnl0ZXMgc2hvdWxkIGxlbmd0aC1w
cmVmaXggdGhlIGJ5dGVzIG9udG8gdGhlCiAgICAgICAgICMgd2lyZS4KICAgICAgICAgZXhwZWN0
ZWRfYnl0ZXMgPSAiZm9vXG43XG5hYmNkZWZnZG9uZVxuIgogICAgICAgICBpbnB1dCA9IFN0cmlu
Z0lPKCJcbiIpCiAgICAgICAgIG91dHB1dCA9IFN0cmluZ0lPKCkKLSAgICAgICAgbWVkaXVtID0g
c21hcnQuU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwgb3V0cHV0KQotICAgICAg
ICBwcm90b2NvbCA9IHNtYXJ0LlNtYXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKG1lZGl1bS5n
ZXRfcmVxdWVzdCgpKQotICAgICAgICBwcm90b2NvbC5jYWxsX3dpdGhfYm9keV9ieXRlcygoJ2Zv
bycsICksICJhYmNkZWZnIikKKyAgICAgICAgY2xpZW50X21lZGl1bSA9IG1lZGl1bS5TbWFydFNp
bXBsZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCisgICAgICAgIHJlcXVlc3QgPSBj
bGllbnRfbWVkaXVtLmdldF9yZXF1ZXN0KCkKKyAgICAgICAgc21hcnRfcHJvdG9jb2wgPSBwcm90
b2NvbC5TbWFydENsaWVudFJlcXVlc3RQcm90b2NvbE9uZShyZXF1ZXN0KQorICAgICAgICBzbWFy
dF9wcm90b2NvbC5jYWxsX3dpdGhfYm9keV9ieXRlcygoJ2ZvbycsICksICJhYmNkZWZnIikKICAg
ICAgICAgc2VsZi5hc3NlcnRFcXVhbChleHBlY3RlZF9ieXRlcywgb3V0cHV0LmdldHZhbHVlKCkp
CiAKICAgICBkZWYgdGVzdF9jbGllbnRfY2FsbF93aXRoX2JvZHlfcmVhZHZfYXJyYXkoc2VsZik6
CkBAIC0xMjY0LDkgKzEyODcsMTAgQEAKICAgICAgICAgZXhwZWN0ZWRfYnl0ZXMgPSAiZm9vXG43
XG4xLDJcbjUsNmRvbmVcbiIKICAgICAgICAgaW5wdXQgPSBTdHJpbmdJTygiXG4iKQogICAgICAg
ICBvdXRwdXQgPSBTdHJpbmdJTygpCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U2ltcGxl
UGlwZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKLSAgICAgICAgcHJvdG9jb2wgPSBzbWFy
dC5TbWFydENsaWVudFJlcXVlc3RQcm90b2NvbE9uZShtZWRpdW0uZ2V0X3JlcXVlc3QoKSkKLSAg
ICAgICAgcHJvdG9jb2wuY2FsbF93aXRoX2JvZHlfcmVhZHZfYXJyYXkoKCdmb28nLCApLCBbKDEs
MiksKDUsNildKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVtLlNtYXJ0U2ltcGxlUGlw
ZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKKyAgICAgICAgcmVxdWVzdCA9IGNsaWVudF9t
ZWRpdW0uZ2V0X3JlcXVlc3QoKQorICAgICAgICBzbWFydF9wcm90b2NvbCA9IHByb3RvY29sLlNt
YXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKHJlcXVlc3QpCisgICAgICAgIHNtYXJ0X3Byb3Rv
Y29sLmNhbGxfd2l0aF9ib2R5X3JlYWR2X2FycmF5KCgnZm9vJywgKSwgWygxLDIpLCg1LDYpXSkK
ICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChleHBlY3RlZF9ieXRlcywgb3V0cHV0LmdldHZhbHVl
KCkpCiAKICAgICBkZWYgdGVzdF9jbGllbnRfcmVhZF9ib2R5X2J5dGVzX2FsbChzZWxmKToKQEAg
LTEyNzYsMTEgKzEzMDAsMTIgQEAKICAgICAgICAgc2VydmVyX2J5dGVzID0gIm9rXG43XG4xMjM0
NTY3ZG9uZVxuIgogICAgICAgICBpbnB1dCA9IFN0cmluZ0lPKHNlcnZlcl9ieXRlcykKICAgICAg
ICAgb3V0cHV0ID0gU3RyaW5nSU8oKQotICAgICAgICBtZWRpdW0gPSBzbWFydC5TbWFydFNpbXBs
ZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQpCi0gICAgICAgIHByb3RvY29sID0gc21h
cnQuU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9jb2xPbmUobWVkaXVtLmdldF9yZXF1ZXN0KCkpCi0g
ICAgICAgIHByb3RvY29sLmNhbGwoJ2ZvbycpCi0gICAgICAgIHByb3RvY29sLnJlYWRfcmVzcG9u
c2VfdHVwbGUoVHJ1ZSkKLSAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChleHBlY3RlZF9ieXRlcywg
cHJvdG9jb2wucmVhZF9ib2R5X2J5dGVzKCkpCisgICAgICAgIGNsaWVudF9tZWRpdW0gPSBtZWRp
dW0uU21hcnRTaW1wbGVQaXBlc0NsaWVudE1lZGl1bShpbnB1dCwgb3V0cHV0KQorICAgICAgICBy
ZXF1ZXN0ID0gY2xpZW50X21lZGl1bS5nZXRfcmVxdWVzdCgpCisgICAgICAgIHNtYXJ0X3Byb3Rv
Y29sID0gcHJvdG9jb2wuU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9jb2xPbmUocmVxdWVzdCkKKyAg
ICAgICAgc21hcnRfcHJvdG9jb2wuY2FsbCgnZm9vJykKKyAgICAgICAgc21hcnRfcHJvdG9jb2wu
cmVhZF9yZXNwb25zZV90dXBsZShUcnVlKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGV4cGVj
dGVkX2J5dGVzLCBzbWFydF9wcm90b2NvbC5yZWFkX2JvZHlfYnl0ZXMoKSkKIAogICAgIGRlZiB0
ZXN0X2NsaWVudF9yZWFkX2JvZHlfYnl0ZXNfaW5jcmVtZW50YWwoc2VsZik6CiAgICAgICAgICMg
dGVzdCByZWFkaW5nIGEgZmV3IGJ5dGVzIGF0IGEgdGltZSBmcm9tIHRoZSBib2R5CkBAIC0xMjky
LDE0ICsxMzE3LDE1IEBACiAgICAgICAgIHNlcnZlcl9ieXRlcyA9ICJva1xuN1xuMTIzNDU2N2Rv
bmVcbiIKICAgICAgICAgaW5wdXQgPSBTdHJpbmdJTyhzZXJ2ZXJfYnl0ZXMpCiAgICAgICAgIG91
dHB1dCA9IFN0cmluZ0lPKCkKLSAgICAgICAgbWVkaXVtID0gc21hcnQuU21hcnRTaW1wbGVQaXBl
c0NsaWVudE1lZGl1bShpbnB1dCwgb3V0cHV0KQotICAgICAgICBwcm90b2NvbCA9IHNtYXJ0LlNt
YXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKG1lZGl1bS5nZXRfcmVxdWVzdCgpKQotICAgICAg
ICBwcm90b2NvbC5jYWxsKCdmb28nKQotICAgICAgICBwcm90b2NvbC5yZWFkX3Jlc3BvbnNlX3R1
cGxlKFRydWUpCi0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoZXhwZWN0ZWRfYnl0ZXNbMDoyXSwg
cHJvdG9jb2wucmVhZF9ib2R5X2J5dGVzKDIpKQotICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGV4
cGVjdGVkX2J5dGVzWzI6NF0sIHByb3RvY29sLnJlYWRfYm9keV9ieXRlcygyKSkKLSAgICAgICAg
c2VsZi5hc3NlcnRFcXVhbChleHBlY3RlZF9ieXRlc1s0OjZdLCBwcm90b2NvbC5yZWFkX2JvZHlf
Ynl0ZXMoMikpCi0gICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoZXhwZWN0ZWRfYnl0ZXNbNl0sIHBy
b3RvY29sLnJlYWRfYm9keV9ieXRlcygpKQorICAgICAgICBjbGllbnRfbWVkaXVtID0gbWVkaXVt
LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRpdW0oaW5wdXQsIG91dHB1dCkKKyAgICAgICAgcmVx
dWVzdCA9IGNsaWVudF9tZWRpdW0uZ2V0X3JlcXVlc3QoKQorICAgICAgICBzbWFydF9wcm90b2Nv
bCA9IHByb3RvY29sLlNtYXJ0Q2xpZW50UmVxdWVzdFByb3RvY29sT25lKHJlcXVlc3QpCisgICAg
ICAgIHNtYXJ0X3Byb3RvY29sLmNhbGwoJ2ZvbycpCisgICAgICAgIHNtYXJ0X3Byb3RvY29sLnJl
YWRfcmVzcG9uc2VfdHVwbGUoVHJ1ZSkKKyAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChleHBlY3Rl
ZF9ieXRlc1swOjJdLCBzbWFydF9wcm90b2NvbC5yZWFkX2JvZHlfYnl0ZXMoMikpCisgICAgICAg
IHNlbGYuYXNzZXJ0RXF1YWwoZXhwZWN0ZWRfYnl0ZXNbMjo0XSwgc21hcnRfcHJvdG9jb2wucmVh
ZF9ib2R5X2J5dGVzKDIpKQorICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGV4cGVjdGVkX2J5dGVz
WzQ6Nl0sIHNtYXJ0X3Byb3RvY29sLnJlYWRfYm9keV9ieXRlcygyKSkKKyAgICAgICAgc2VsZi5h
c3NlcnRFcXVhbChleHBlY3RlZF9ieXRlc1s2XSwgc21hcnRfcHJvdG9jb2wucmVhZF9ib2R5X2J5
dGVzKCkpCiAKICAgICBkZWYgdGVzdF9jbGllbnRfY2FuY2VsX3JlYWRfYm9keV9kb2VzX25vdF9l
YXRfYm9keV9ieXRlcyhzZWxmKToKICAgICAgICAgIyBjYW5jZWxsaW5nIHRoZSBleHBlY3RlZCBi
b2R5IG5lZWRzIHRvIGZpbmlzaCB0aGUgcmVxdWVzdCwgYnV0IG5vdApAQCAtMTMwOCwxMyArMTMz
NCwxNSBAQAogICAgICAgICBzZXJ2ZXJfYnl0ZXMgPSAib2tcbjdcbjEyMzQ1Njdkb25lXG4iCiAg
ICAgICAgIGlucHV0ID0gU3RyaW5nSU8oc2VydmVyX2J5dGVzKQogICAgICAgICBvdXRwdXQgPSBT
dHJpbmdJTygpCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRN
ZWRpdW0oaW5wdXQsIG91dHB1dCkKLSAgICAgICAgcHJvdG9jb2wgPSBzbWFydC5TbWFydENsaWVu
dFJlcXVlc3RQcm90b2NvbE9uZShtZWRpdW0uZ2V0X3JlcXVlc3QoKSkKLSAgICAgICAgcHJvdG9j
b2wuY2FsbCgnZm9vJykKLSAgICAgICAgcHJvdG9jb2wucmVhZF9yZXNwb25zZV90dXBsZShUcnVl
KQotICAgICAgICBwcm90b2NvbC5jYW5jZWxfcmVhZF9ib2R5KCkKKyAgICAgICAgY2xpZW50X21l
ZGl1bSA9IG1lZGl1bS5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVtKGlucHV0LCBvdXRwdXQp
CisgICAgICAgIHJlcXVlc3QgPSBjbGllbnRfbWVkaXVtLmdldF9yZXF1ZXN0KCkKKyAgICAgICAg
c21hcnRfcHJvdG9jb2wgPSBwcm90b2NvbC5TbWFydENsaWVudFJlcXVlc3RQcm90b2NvbE9uZShy
ZXF1ZXN0KQorICAgICAgICBzbWFydF9wcm90b2NvbC5jYWxsKCdmb28nKQorICAgICAgICBzbWFy
dF9wcm90b2NvbC5yZWFkX3Jlc3BvbnNlX3R1cGxlKFRydWUpCisgICAgICAgIHNtYXJ0X3Byb3Rv
Y29sLmNhbmNlbF9yZWFkX2JvZHkoKQogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKDMsIGlucHV0
LnRlbGwoKSkKLSAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMoZXJyb3JzLlJlYWRpbmdDb21wbGV0
ZWQsIHByb3RvY29sLnJlYWRfYm9keV9ieXRlcykKKyAgICAgICAgc2VsZi5hc3NlcnRSYWlzZXMo
CisgICAgICAgICAgICBlcnJvcnMuUmVhZGluZ0NvbXBsZXRlZCwgc21hcnRfcHJvdG9jb2wucmVh
ZF9ib2R5X2J5dGVzKQogCiAKIGNsYXNzIExlbmd0aFByZWZpeGVkQm9keURlY29kZXIodGVzdHMu
VGVzdENhc2UpOgpAQCAtMTMyMywxNCArMTM1MSwxNCBAQAogICAgICMgc29tZXRoaW5nIHNpbWls
YXIgdG8gdGhlIFByb3RvY29sQmFzZSBtZXRob2QuCiAKICAgICBkZWYgdGVzdF9jb25zdHJ1Y3Qo
c2VsZik6Ci0gICAgICAgIGRlY29kZXIgPSBzbWFydC5MZW5ndGhQcmVmaXhlZEJvZHlEZWNvZGVy
KCkKKyAgICAgICAgZGVjb2RlciA9IHByb3RvY29sLkxlbmd0aFByZWZpeGVkQm9keURlY29kZXIo
KQogICAgICAgICBzZWxmLmFzc2VydEZhbHNlKGRlY29kZXIuZmluaXNoZWRfcmVhZGluZykKICAg
ICAgICAgc2VsZi5hc3NlcnRFcXVhbCg2LCBkZWNvZGVyLm5leHRfcmVhZF9zaXplKCkpCiAgICAg
ICAgIHNlbGYuYXNzZXJ0RXF1YWwoJycsIGRlY29kZXIucmVhZF9wZW5kaW5nX2RhdGEoKSkKICAg
ICAgICAgc2VsZi5hc3NlcnRFcXVhbCgnJywgZGVjb2Rlci51bnVzZWRfZGF0YSkKIAogICAgIGRl
ZiB0ZXN0X2FjY2VwdF9ieXRlcyhzZWxmKToKLSAgICAgICAgZGVjb2RlciA9IHNtYXJ0Lkxlbmd0
aFByZWZpeGVkQm9keURlY29kZXIoKQorICAgICAgICBkZWNvZGVyID0gcHJvdG9jb2wuTGVuZ3Ro
UHJlZml4ZWRCb2R5RGVjb2RlcigpCiAgICAgICAgIGRlY29kZXIuYWNjZXB0X2J5dGVzKCcnKQog
ICAgICAgICBzZWxmLmFzc2VydEZhbHNlKGRlY29kZXIuZmluaXNoZWRfcmVhZGluZykKICAgICAg
ICAgc2VsZi5hc3NlcnRFcXVhbCg2LCBkZWNvZGVyLm5leHRfcmVhZF9zaXplKCkpCkBAIC0xMzYz
LDcgKzEzOTEsNyBAQAogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCdibGFyZycsIGRlY29kZXIu
dW51c2VkX2RhdGEpCiAgICAgICAgIAogICAgIGRlZiB0ZXN0X2FjY2VwdF9ieXRlc19hbGxfYXRf
b25jZV93aXRoX2V4Y2VzcyhzZWxmKToKLSAgICAgICAgZGVjb2RlciA9IHNtYXJ0Lkxlbmd0aFBy
ZWZpeGVkQm9keURlY29kZXIoKQorICAgICAgICBkZWNvZGVyID0gcHJvdG9jb2wuTGVuZ3RoUHJl
Zml4ZWRCb2R5RGVjb2RlcigpCiAgICAgICAgIGRlY29kZXIuYWNjZXB0X2J5dGVzKCcxXG5hZG9u
ZVxudW51c2VkJykKICAgICAgICAgc2VsZi5hc3NlcnRUcnVlKGRlY29kZXIuZmluaXNoZWRfcmVh
ZGluZykKICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCgxLCBkZWNvZGVyLm5leHRfcmVhZF9zaXpl
KCkpCkBAIC0xMzcxLDcgKzEzOTksNyBAQAogICAgICAgICBzZWxmLmFzc2VydEVxdWFsKCd1bnVz
ZWQnLCBkZWNvZGVyLnVudXNlZF9kYXRhKQogCiAgICAgZGVmIHRlc3RfYWNjZXB0X2J5dGVzX2V4
YWN0X2VuZF9vZl9ib2R5KHNlbGYpOgotICAgICAgICBkZWNvZGVyID0gc21hcnQuTGVuZ3RoUHJl
Zml4ZWRCb2R5RGVjb2RlcigpCisgICAgICAgIGRlY29kZXIgPSBwcm90b2NvbC5MZW5ndGhQcmVm
aXhlZEJvZHlEZWNvZGVyKCkKICAgICAgICAgZGVjb2Rlci5hY2NlcHRfYnl0ZXMoJzFcbmEnKQog
ICAgICAgICBzZWxmLmFzc2VydEZhbHNlKGRlY29kZXIuZmluaXNoZWRfcmVhZGluZykKICAgICAg
ICAgc2VsZi5hc3NlcnRFcXVhbCg1LCBkZWNvZGVyLm5leHRfcmVhZF9zaXplKCkpCkBAIC0xMzk1
LDIxICsxNDIzLDIyIEBACiAKIGNsYXNzIEhUVFBUdW5uZWxsaW5nU21va2VUZXN0KHRlc3RzLlRl
c3RDYXNlV2l0aFRyYW5zcG9ydCk6CiAgICAgCisgICAgZGVmIHNldFVwKHNlbGYpOgorICAgICAg
ICBzdXBlcihIVFRQVHVubmVsbGluZ1Ntb2tlVGVzdCwgc2VsZikuc2V0VXAoKQorICAgICAgICAj
IFdlIHVzZSB0aGUgVkZTIGxheWVyIGFzIHBhcnQgb2YgSFRUUCB0dW5uZWxsaW5nIHRlc3RzLgor
ICAgICAgICBzZWxmLl9jYXB0dXJlVmFyKCdOT19TTUFSVF9WRlMnLCBOb25lKQorCiAgICAgZGVm
IF90ZXN0X2J1bGtfZGF0YShzZWxmLCB1cmxfcHJvdG9jb2wpOgogICAgICAgICAjIFdlIHNob3Vs
ZCBiZSBhYmxlIHRvIHNlbmQgYW5kIHJlY2VpdmUgYnVsayBkYXRhIGluIGEgc2luZ2xlIG1lc3Nh
Z2UuCiAgICAgICAgICMgVGhlICdyZWFkdicgY29tbWFuZCBpbiB0aGUgc21hcnQgcHJvdG9jb2wg
Ym90aCBzZW5kcyBhbmQgcmVjZWl2ZXMgYnVsawogICAgICAgICAjIGRhdGEsIHNvIHdlIHVzZSB0
aGF0LgogICAgICAgICBzZWxmLmJ1aWxkX3RyZWUoWydkYXRhLWZpbGUnXSkKLSAgICAgICAgaHR0
cF9zZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNtYXJ0cygpCi0gICAgICAgIGh0dHBfc2VydmVyLl91
cmxfcHJvdG9jb2wgPSB1cmxfcHJvdG9jb2wKLSAgICAgICAgaHR0cF9zZXJ2ZXIuc2V0VXAoKQot
ICAgICAgICBzZWxmLmFkZENsZWFudXAoaHR0cF9zZXJ2ZXIudGVhckRvd24pCi0KLSAgICAgICAg
aHR0cF90cmFuc3BvcnQgPSBnZXRfdHJhbnNwb3J0KGh0dHBfc2VydmVyLmdldF91cmwoKSkKLQor
ICAgICAgICBzZWxmLnRyYW5zcG9ydF9yZWFkb25seV9zZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNt
YXJ0cworCisgICAgICAgIGh0dHBfdHJhbnNwb3J0ID0gc2VsZi5nZXRfcmVhZG9ubHlfdHJhbnNw
b3J0KCkKICAgICAgICAgbWVkaXVtID0gaHR0cF90cmFuc3BvcnQuZ2V0X3NtYXJ0X21lZGl1bSgp
CiAgICAgICAgICNyZW1vdGVfdHJhbnNwb3J0ID0gUmVtb3RlVHJhbnNwb3J0KCdmYWtlX3VybCcs
IG1lZGl1bSkKLSAgICAgICAgcmVtb3RlX3RyYW5zcG9ydCA9IHNtYXJ0LlNtYXJ0VHJhbnNwb3J0
KCcvJywgbWVkaXVtPW1lZGl1bSkKKyAgICAgICAgcmVtb3RlX3RyYW5zcG9ydCA9IHJlbW90ZS5T
bWFydFRyYW5zcG9ydCgnLycsIG1lZGl1bT1tZWRpdW0pCiAgICAgICAgIHNlbGYuYXNzZXJ0RXF1
YWwoCiAgICAgICAgICAgICBbKDAsICJjIildLCBsaXN0KHJlbW90ZV90cmFuc3BvcnQucmVhZHYo
ImRhdGEtZmlsZSIsIFsoMCwxKV0pKSkKIApAQCAtMTQzNCw3ICsxNDYzLDcgQEAKICAgICBkZWYg
X3Rlc3RfaHR0cF9zZW5kX3NtYXJ0X3JlcXVlc3Qoc2VsZiwgdXJsX3Byb3RvY29sKToKICAgICAg
ICAgaHR0cF9zZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNtYXJ0cygpCiAgICAgICAgIGh0dHBfc2Vy
dmVyLl91cmxfcHJvdG9jb2wgPSB1cmxfcHJvdG9jb2wKLSAgICAgICAgaHR0cF9zZXJ2ZXIuc2V0
VXAoKQorICAgICAgICBodHRwX3NlcnZlci5zZXRVcChzZWxmLmdldF92ZnNfb25seV9zZXJ2ZXIo
KSkKICAgICAgICAgc2VsZi5hZGRDbGVhbnVwKGh0dHBfc2VydmVyLnRlYXJEb3duKQogCiAgICAg
ICAgIHBvc3RfYm9keSA9ICdoZWxsb1xuJwpAQCAtMTQ1NiwyMyArMTQ4NSwxOSBAQAogICAgICAg
ICBzZWxmLl90ZXN0X2h0dHBfc2VuZF9zbWFydF9yZXF1ZXN0KCdodHRwK3VybGxpYicpCiAKICAg
ICBkZWYgdGVzdF9odHRwX3NlcnZlcl93aXRoX3NtYXJ0cyhzZWxmKToKLSAgICAgICAgaHR0cF9z
ZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNtYXJ0cygpCi0gICAgICAgIGh0dHBfc2VydmVyLnNldFVw
KCkKLSAgICAgICAgc2VsZi5hZGRDbGVhbnVwKGh0dHBfc2VydmVyLnRlYXJEb3duKQorICAgICAg
ICBzZWxmLnRyYW5zcG9ydF9yZWFkb25seV9zZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNtYXJ0cwog
CiAgICAgICAgIHBvc3RfYm9keSA9ICdoZWxsb1xuJwogICAgICAgICBleHBlY3RlZF9yZXBseV9i
b2R5ID0gJ29rXHgwMTFcbicKIAotICAgICAgICBzbWFydF9zZXJ2ZXJfdXJsID0gaHR0cF9zZXJ2
ZXIuZ2V0X3VybCgpICsgJy5ienIvc21hcnQnCisgICAgICAgIHNtYXJ0X3NlcnZlcl91cmwgPSBz
ZWxmLmdldF9yZWFkb25seV91cmwoJy5ienIvc21hcnQnKQogICAgICAgICByZXBseSA9IHVybGxp
YjIudXJsb3BlbihzbWFydF9zZXJ2ZXJfdXJsLCBwb3N0X2JvZHkpLnJlYWQoKQogCiAgICAgICAg
IHNlbGYuYXNzZXJ0RXF1YWwoZXhwZWN0ZWRfcmVwbHlfYm9keSwgcmVwbHkpCiAKICAgICBkZWYg
dGVzdF9zbWFydF9odHRwX3NlcnZlcl9wb3N0X3JlcXVlc3RfaGFuZGxlcihzZWxmKToKLSAgICAg
ICAgaHR0cF9zZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNtYXJ0cygpCi0gICAgICAgIGh0dHBfc2Vy
dmVyLnNldFVwKCkKLSAgICAgICAgc2VsZi5hZGRDbGVhbnVwKGh0dHBfc2VydmVyLnRlYXJEb3du
KQotICAgICAgICBodHRwZCA9IGh0dHBfc2VydmVyLl9nZXRfaHR0cGQoKQorICAgICAgICBzZWxm
LnRyYW5zcG9ydF9yZWFkb25seV9zZXJ2ZXIgPSBIVFRQU2VydmVyV2l0aFNtYXJ0cworICAgICAg
ICBodHRwZCA9IHNlbGYuZ2V0X3JlYWRvbmx5X3NlcnZlcigpLl9nZXRfaHR0cGQoKQogCiAgICAg
ICAgIHNvY2tldCA9IFNhbXBsZVNvY2tldCgKICAgICAgICAgICAgICdQT1NUIC8uYnpyL3NtYXJ0
IEhUVFAvMS4wXHJcbicKQEAgLTE1MTQsNyArMTUzOSw3IEBACiAgICAgICAgIGVsc2U6CiAgICAg
ICAgICAgICByZXR1cm4gc2VsZi53cml0ZWZpbGUKIAotICAgICAgICAKKwogIyBUT0RPOiBDbGll
bnQgZmVhdHVyZSB0aGF0IGRvZXMgZ2V0X2J1bmRsZSBhbmQgdGhlbiBpbnN0YWxscyB0aGF0IGlu
dG8gYQogIyBicmFuY2g7IHRoaXMgY2FuIGJlIHVzZWQgaW4gcGxhY2Ugb2YgdGhlIHJlZ3VsYXIg
cHVsbC9mZXRjaCBvcGVyYXRpb24gd2hlbgogIyBjb21pbmcgZnJvbSBhIHNtYXJ0IHNlcnZlci4K
Cg==

=== modified file bzrlib/tests/test_transport_implementations.py // encoding:ba
... se64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydF9pbXBsZW1lbnRhdGlvbnMucHkKKysrIGJ6
cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydF9pbXBsZW1lbnRhdGlvbnMucHkKQEAgLTM4LDYgKzM4
LDcgQEAKIGZyb20gYnpybGliLnN5bWJvbF92ZXJzaW9uaW5nIGltcG9ydCB6ZXJvX2VsZXZlbgog
ZnJvbSBienJsaWIudGVzdHMgaW1wb3J0IFRlc3RDYXNlSW5UZW1wRGlyLCBUZXN0U2tpcHBlZAog
ZnJvbSBienJsaWIudGVzdHMudGVzdF90cmFuc3BvcnQgaW1wb3J0IFRlc3RUcmFuc3BvcnRJbXBs
ZW1lbnRhdGlvbgorZnJvbSBienJsaWIuc21hcnQgaW1wb3J0IG1lZGl1bQogZnJvbSBienJsaWIu
dHJhbnNwb3J0IGltcG9ydCBtZW1vcnksIHJlbW90ZQogaW1wb3J0IGJ6cmxpYi50cmFuc3BvcnQK
IApAQCAtMTMwNiw3ICsxMzA3LDcgQEAKICAgICAgICAgdHJhbnNwb3J0ID0gc2VsZi5nZXRfdHJh
bnNwb3J0KCkKICAgICAgICAgdHJ5OgogICAgICAgICAgICAgY2xpZW50X21lZGl1bSA9IHRyYW5z
cG9ydC5nZXRfc21hcnRfbWVkaXVtKCkKLSAgICAgICAgICAgIHNlbGYuYXNzZXJ0SXNJbnN0YW5j
ZShjbGllbnRfbWVkaXVtLCByZW1vdGUuU21hcnRDbGllbnRNZWRpdW0pCisgICAgICAgICAgICBz
ZWxmLmFzc2VydElzSW5zdGFuY2UoY2xpZW50X21lZGl1bSwgbWVkaXVtLlNtYXJ0Q2xpZW50TWVk
aXVtKQogICAgICAgICBleGNlcHQgZXJyb3JzLk5vU21hcnRNZWRpdW06CiAgICAgICAgICAgICAj
IGFzIGxvbmcgYXMgd2UgZ290IGl0IHdlJ3JlIGZpbmUKICAgICAgICAgICAgIHBhc3MKCg==

=== modified file bzrlib/transport/http/__init__.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvaHR0cC9fX2luaXRfXy5weQorKysgYnpybGliL3RyYW5zcG9y
dC9odHRwL19faW5pdF9fLnB5CkBAIC0yNyw5ICsyNyw5IEBACiBpbXBvcnQgc3lzCiAKIGZyb20g
YnpybGliIGltcG9ydCBlcnJvcnMsIHVpCitmcm9tIGJ6cmxpYi5zbWFydCBpbXBvcnQgbWVkaXVt
CiBmcm9tIGJ6cmxpYi50cmFjZSBpbXBvcnQgbXV0dGVyCiBmcm9tIGJ6cmxpYi50cmFuc3BvcnQg
aW1wb3J0ICgKLSAgICByZW1vdGUsCiAgICAgVHJhbnNwb3J0LAogICAgICkKIApAQCAtMTEzLDcg
KzExMyw3IEBACiAgICAgcmV0dXJuIG0KIAogCi1jbGFzcyBIdHRwVHJhbnNwb3J0QmFzZShUcmFu
c3BvcnQsIHJlbW90ZS5TbWFydENsaWVudE1lZGl1bSk6CitjbGFzcyBIdHRwVHJhbnNwb3J0QmFz
ZShUcmFuc3BvcnQsIG1lZGl1bS5TbWFydENsaWVudE1lZGl1bSk6CiAgICAgIiIiQmFzZSBjbGFz
cyBmb3IgaHR0cCBpbXBsZW1lbnRhdGlvbnMuCiAKICAgICBEb2VzIFVSTCBwYXJzaW5nLCBldGMs
IGJ1dCBub3QgYW55IG5ldHdvcmsgSU8uCkBAIC01MDUsMTEgKzUwNSwxMSBAQAogICAgICAgICBy
ZXR1cm4gYm9keV9maWxlbGlrZQogCiAKLWNsYXNzIFNtYXJ0Q2xpZW50SFRUUE1lZGl1bVJlcXVl
c3QocmVtb3RlLlNtYXJ0Q2xpZW50TWVkaXVtUmVxdWVzdCk6CitjbGFzcyBTbWFydENsaWVudEhU
VFBNZWRpdW1SZXF1ZXN0KG1lZGl1bS5TbWFydENsaWVudE1lZGl1bVJlcXVlc3QpOgogICAgICIi
IkEgU21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0IHRoYXQgd29ya3Mgd2l0aCBhbiBIVFRQIG1lZGl1
bS4iIiIKIAotICAgIGRlZiBfX2luaXRfXyhzZWxmLCBtZWRpdW0pOgotICAgICAgICByZW1vdGUu
U21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0Ll9faW5pdF9fKHNlbGYsIG1lZGl1bSkKKyAgICBkZWYg
X19pbml0X18oc2VsZiwgc21hcnRfbWVkaXVtKToKKyAgICAgICAgbWVkaXVtLlNtYXJ0Q2xpZW50
TWVkaXVtUmVxdWVzdC5fX2luaXRfXyhzZWxmLCBzbWFydF9tZWRpdW0pCiAgICAgICAgIHNlbGYu
X2J1ZmZlciA9ICcnCiAKICAgICBkZWYgX2FjY2VwdF9ieXRlcyhzZWxmLCBieXRlcyk6Cgo=

=== modified file bzrlib/transport/remote.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvcmVtb3RlLnB5CisrKyBienJsaWIvdHJhbnNwb3J0L3JlbW90
ZS5weQpAQCAtMTUsMjggKzE1LDE1IEBACiAjIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQ
bGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKIAogZnJvbSBjU3Ry
aW5nSU8gaW1wb3J0IFN0cmluZ0lPCi1pbXBvcnQgb3MKLWltcG9ydCBzb2NrZXQKLWltcG9ydCBz
eXMKLWltcG9ydCB0ZW1wZmlsZQotaW1wb3J0IHRocmVhZGluZwogaW1wb3J0IHVybGxpYgogaW1w
b3J0IHVybHBhcnNlCiAKIGZyb20gYnpybGliIGltcG9ydCAoCi0gICAgYnpyZGlyLAogICAgIGVy
cm9ycywKLSAgICByZXZpc2lvbiwKICAgICB0cmFuc3BvcnQsCi0gICAgdHJhY2UsCi0gICAgdXJs
dXRpbHMsCiAgICAgKQotZnJvbSBienJsaWIuYnVuZGxlLnNlcmlhbGl6ZXIgaW1wb3J0IHdyaXRl
X2J1bmRsZQotdHJ5OgotICAgIGZyb20gYnpybGliLnRyYW5zcG9ydCBpbXBvcnQgc3NoCi1leGNl
cHQgZXJyb3JzLlBhcmFtaWtvTm90UHJlc2VudDoKLSAgICAjIG5vIHBhcmFtaWtvLiAgU21hcnRT
U0hDbGllbnRNZWRpdW0gd2lsbCBicmVhay4KLSAgICBwYXNzCitmcm9tIGJ6cmxpYi5zbWFydC5w
cm90b2NvbCBpbXBvcnQgU21hcnRDbGllbnRSZXF1ZXN0UHJvdG9jb2xPbmUKK2Zyb20gYnpybGli
LnNtYXJ0Lm1lZGl1bSBpbXBvcnQgU21hcnRUQ1BDbGllbnRNZWRpdW0sIFNtYXJ0U1NIQ2xpZW50
TWVkaXVtCiAKICMgbXVzdCBkbyB0aGlzIG90aGVyd2lzZSB1cmxsaWIgY2FuJ3QgcGFyc2UgdGhl
IHVybHMgcHJvcGVybHkgOigKIGZvciBzY2hlbWUgaW4gWydzc2gnLCAnYnpyJywgJ2J6citsb29w
YmFjaycsICdienIrc3NoJywgJ2J6citodHRwJ106CkBAIC00OCw1OTcgKzM1LDYgQEAKIEJaUl9E
RUZBVUxUX1BPUlQgPSA0MTU1CiAKIAotZGVmIF9yZWN2X3R1cGxlKGZyb21fZmlsZSk6Ci0gICAg
cmVxX2xpbmUgPSBmcm9tX2ZpbGUucmVhZGxpbmUoKQotICAgIHJldHVybiBfZGVjb2RlX3R1cGxl
KHJlcV9saW5lKQotCi0KLWRlZiBfZGVjb2RlX3R1cGxlKHJlcV9saW5lKToKLSAgICBpZiByZXFf
bGluZSA9PSBOb25lIG9yIHJlcV9saW5lID09ICcnOgotICAgICAgICByZXR1cm4gTm9uZQotICAg
IGlmIHJlcV9saW5lWy0xXSAhPSAnXG4nOgotICAgICAgICByYWlzZSBlcnJvcnMuU21hcnRQcm90
b2NvbEVycm9yKCJyZXF1ZXN0ICVyIG5vdCB0ZXJtaW5hdGVkIiAlIHJlcV9saW5lKQotICAgIHJl
dHVybiB0dXBsZShyZXFfbGluZVs6LTFdLnNwbGl0KCdceDAxJykpCi0KLQotZGVmIF9lbmNvZGVf
dHVwbGUoYXJncyk6Ci0gICAgIiIiRW5jb2RlIHRoZSB0dXBsZSBhcmdzIHRvIGEgYnl0ZXN0cmVh
bS4iIiIKLSAgICByZXR1cm4gJ1x4MDEnLmpvaW4oYXJncykgKyAnXG4nCi0KLQotY2xhc3MgU21h
cnRQcm90b2NvbEJhc2Uob2JqZWN0KToKLSAgICAiIiJNZXRob2RzIGNvbW1vbiB0byBjbGllbnQg
YW5kIHNlcnZlciIiIgotCi0gICAgIyBUT0RPOiB0aGlzIG9ubHkgYWN0dWFsbHkgYWNjb21vZGF0
ZXMgYSBzaW5nbGUgYmxvY2s7IHBvc3NpYmx5IHNob3VsZAotICAgICMgc3VwcG9ydCBtdWx0aXBs
ZSBjaHVua3M/Ci0gICAgZGVmIF9lbmNvZGVfYnVsa19kYXRhKHNlbGYsIGJvZHkpOgotICAgICAg
ICAiIiJFbmNvZGUgYm9keSBhcyBhIGJ1bGsgZGF0YSBjaHVuay4iIiIKLSAgICAgICAgcmV0dXJu
ICcnLmpvaW4oKCclZFxuJyAlIGxlbihib2R5KSwgYm9keSwgJ2RvbmVcbicpKQotCi0gICAgZGVm
IF9zZXJpYWxpc2Vfb2Zmc2V0cyhzZWxmLCBvZmZzZXRzKToKLSAgICAgICAgIiIiU2VyaWFsaXNl
IGEgcmVhZHYgb2Zmc2V0IGxpc3QuIiIiCi0gICAgICAgIHR4dCA9IFtdCi0gICAgICAgIGZvciBz
dGFydCwgbGVuZ3RoIGluIG9mZnNldHM6Ci0gICAgICAgICAgICB0eHQuYXBwZW5kKCclZCwlZCcg
JSAoc3RhcnQsIGxlbmd0aCkpCi0gICAgICAgIHJldHVybiAnXG4nLmpvaW4odHh0KQotICAgICAg
ICAKLQotY2xhc3MgU21hcnRTZXJ2ZXJSZXF1ZXN0UHJvdG9jb2xPbmUoU21hcnRQcm90b2NvbEJh
c2UpOgotICAgICIiIlNlcnZlci1zaWRlIGVuY29kaW5nIGFuZCBkZWNvZGluZyBsb2dpYyBmb3Ig
c21hcnQgdmVyc2lvbiAxLiIiIgotICAgIAotICAgIGRlZiBfX2luaXRfXyhzZWxmLCBiYWNraW5n
X3RyYW5zcG9ydCwgd3JpdGVfZnVuYyk6Ci0gICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0
ID0gYmFja2luZ190cmFuc3BvcnQKLSAgICAgICAgc2VsZi5leGNlc3NfYnVmZmVyID0gJycKLSAg
ICAgICAgc2VsZi5fZmluaXNoZWQgPSBGYWxzZQotICAgICAgICBzZWxmLmluX2J1ZmZlciA9ICcn
Ci0gICAgICAgIHNlbGYuaGFzX2Rpc3BhdGNoZWQgPSBGYWxzZQotICAgICAgICBzZWxmLnJlcXVl
c3QgPSBOb25lCi0gICAgICAgIHNlbGYuX2JvZHlfZGVjb2RlciA9IE5vbmUKLSAgICAgICAgc2Vs
Zi5fd3JpdGVfZnVuYyA9IHdyaXRlX2Z1bmMKLQotICAgIGRlZiBhY2NlcHRfYnl0ZXMoc2VsZiwg
Ynl0ZXMpOgotICAgICAgICAiIiJUYWtlIGJ5dGVzLCBhbmQgYWR2YW5jZSB0aGUgaW50ZXJuYWwg
c3RhdGUgbWFjaGluZSBhcHByb3ByaWF0ZWx5LgotICAgICAgICAKLSAgICAgICAgOnBhcmFtIGJ5
dGVzOiBtdXN0IGJlIGEgYnl0ZSBzdHJpbmcKLSAgICAgICAgIiIiCi0gICAgICAgIGFzc2VydCBp
c2luc3RhbmNlKGJ5dGVzLCBzdHIpCi0gICAgICAgIHNlbGYuaW5fYnVmZmVyICs9IGJ5dGVzCi0g
ICAgICAgIGlmIG5vdCBzZWxmLmhhc19kaXNwYXRjaGVkOgotICAgICAgICAgICAgaWYgJ1xuJyBu
b3QgaW4gc2VsZi5pbl9idWZmZXI6Ci0gICAgICAgICAgICAgICAgIyBubyBjb21tYW5kIGxpbmUg
eWV0Ci0gICAgICAgICAgICAgICAgcmV0dXJuCi0gICAgICAgICAgICBzZWxmLmhhc19kaXNwYXRj
aGVkID0gVHJ1ZQotICAgICAgICAgICAgdHJ5OgotICAgICAgICAgICAgICAgIGZpcnN0X2xpbmUs
IHNlbGYuaW5fYnVmZmVyID0gc2VsZi5pbl9idWZmZXIuc3BsaXQoJ1xuJywgMSkKLSAgICAgICAg
ICAgICAgICBmaXJzdF9saW5lICs9ICdcbicKLSAgICAgICAgICAgICAgICByZXFfYXJncyA9IF9k
ZWNvZGVfdHVwbGUoZmlyc3RfbGluZSkKLSAgICAgICAgICAgICAgICBzZWxmLnJlcXVlc3QgPSBT
bWFydFNlcnZlclJlcXVlc3RIYW5kbGVyKAotICAgICAgICAgICAgICAgICAgICBzZWxmLl9iYWNr
aW5nX3RyYW5zcG9ydCkKLSAgICAgICAgICAgICAgICBzZWxmLnJlcXVlc3QuZGlzcGF0Y2hfY29t
bWFuZChyZXFfYXJnc1swXSwgcmVxX2FyZ3NbMTpdKQotICAgICAgICAgICAgICAgIGlmIHNlbGYu
cmVxdWVzdC5maW5pc2hlZF9yZWFkaW5nOgotICAgICAgICAgICAgICAgICAgICAjIHRyaXZpYWwg
cmVxdWVzdAotICAgICAgICAgICAgICAgICAgICBzZWxmLmV4Y2Vzc19idWZmZXIgPSBzZWxmLmlu
X2J1ZmZlcgotICAgICAgICAgICAgICAgICAgICBzZWxmLmluX2J1ZmZlciA9ICcnCi0gICAgICAg
ICAgICAgICAgICAgIHNlbGYuX3NlbmRfcmVzcG9uc2Uoc2VsZi5yZXF1ZXN0LnJlc3BvbnNlLmFy
Z3MsCi0gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlcXVlc3QucmVzcG9uc2UuYm9keSkK
LSAgICAgICAgICAgIGV4Y2VwdCBLZXlib2FyZEludGVycnVwdDoKLSAgICAgICAgICAgICAgICBy
YWlzZQotICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiwgZXhjZXB0aW9uOgotICAgICAgICAg
ICAgICAgICMgZXZlcnl0aGluZyBlbHNlOiBwYXNzIHRvIGNsaWVudCwgZmx1c2gsIGFuZCBxdWl0
Ci0gICAgICAgICAgICAgICAgc2VsZi5fc2VuZF9yZXNwb25zZSgoJ2Vycm9yJywgc3RyKGV4Y2Vw
dGlvbikpKQotICAgICAgICAgICAgICAgIHJldHVybgotCi0gICAgICAgIGlmIHNlbGYuaGFzX2Rp
c3BhdGNoZWQ6Ci0gICAgICAgICAgICBpZiBzZWxmLl9maW5pc2hlZDoKLSAgICAgICAgICAgICAg
ICAjIG5vdGhpbmcgdG8gZG8uWFhYOiB0aGlzIHJvdXRpbmUgc2hvdWxkIGJlIGEgc2luZ2xlIHN0
YXRlIAotICAgICAgICAgICAgICAgICMgbWFjaGluZSB0b28uCi0gICAgICAgICAgICAgICAgc2Vs
Zi5leGNlc3NfYnVmZmVyICs9IHNlbGYuaW5fYnVmZmVyCi0gICAgICAgICAgICAgICAgc2VsZi5p
bl9idWZmZXIgPSAnJwotICAgICAgICAgICAgICAgIHJldHVybgotICAgICAgICAgICAgaWYgc2Vs
Zi5fYm9keV9kZWNvZGVyIGlzIE5vbmU6Ci0gICAgICAgICAgICAgICAgc2VsZi5fYm9keV9kZWNv
ZGVyID0gTGVuZ3RoUHJlZml4ZWRCb2R5RGVjb2RlcigpCi0gICAgICAgICAgICBzZWxmLl9ib2R5
X2RlY29kZXIuYWNjZXB0X2J5dGVzKHNlbGYuaW5fYnVmZmVyKQotICAgICAgICAgICAgc2VsZi5p
bl9idWZmZXIgPSBzZWxmLl9ib2R5X2RlY29kZXIudW51c2VkX2RhdGEKLSAgICAgICAgICAgIGJv
ZHlfZGF0YSA9IHNlbGYuX2JvZHlfZGVjb2Rlci5yZWFkX3BlbmRpbmdfZGF0YSgpCi0gICAgICAg
ICAgICBzZWxmLnJlcXVlc3QuYWNjZXB0X2JvZHkoYm9keV9kYXRhKQotICAgICAgICAgICAgaWYg
c2VsZi5fYm9keV9kZWNvZGVyLmZpbmlzaGVkX3JlYWRpbmc6Ci0gICAgICAgICAgICAgICAgc2Vs
Zi5yZXF1ZXN0LmVuZF9vZl9ib2R5KCkKLSAgICAgICAgICAgICAgICBhc3NlcnQgc2VsZi5yZXF1
ZXN0LmZpbmlzaGVkX3JlYWRpbmcsIFwKLSAgICAgICAgICAgICAgICAgICAgIm5vIG1vcmUgYm9k
eSwgcmVxdWVzdCBub3QgZmluaXNoZWQiCi0gICAgICAgICAgICBpZiBzZWxmLnJlcXVlc3QucmVz
cG9uc2UgaXMgbm90IE5vbmU6Ci0gICAgICAgICAgICAgICAgc2VsZi5fc2VuZF9yZXNwb25zZShz
ZWxmLnJlcXVlc3QucmVzcG9uc2UuYXJncywKLSAgICAgICAgICAgICAgICAgICAgc2VsZi5yZXF1
ZXN0LnJlc3BvbnNlLmJvZHkpCi0gICAgICAgICAgICAgICAgc2VsZi5leGNlc3NfYnVmZmVyID0g
c2VsZi5pbl9idWZmZXIKLSAgICAgICAgICAgICAgICBzZWxmLmluX2J1ZmZlciA9ICcnCi0gICAg
ICAgICAgICBlbHNlOgotICAgICAgICAgICAgICAgIGFzc2VydCBub3Qgc2VsZi5yZXF1ZXN0LmZp
bmlzaGVkX3JlYWRpbmcsIFwKLSAgICAgICAgICAgICAgICAgICAgIm5vIHJlc3BvbnNlIGFuZCB3
ZSBoYXZlIGZpbmlzaGVkIHJlYWRpbmcuIgotCi0gICAgZGVmIF9zZW5kX3Jlc3BvbnNlKHNlbGYs
IGFyZ3MsIGJvZHk9Tm9uZSk6Ci0gICAgICAgICIiIlNlbmQgYSBzbWFydCBzZXJ2ZXIgcmVzcG9u
c2UgZG93biB0aGUgb3V0cHV0IHN0cmVhbS4iIiIKLSAgICAgICAgYXNzZXJ0IG5vdCBzZWxmLl9m
aW5pc2hlZCwgJ3Jlc3BvbnNlIGFscmVhZHkgc2VudCcKLSAgICAgICAgc2VsZi5fZmluaXNoZWQg
PSBUcnVlCi0gICAgICAgIHNlbGYuX3dyaXRlX2Z1bmMoX2VuY29kZV90dXBsZShhcmdzKSkKLSAg
ICAgICAgaWYgYm9keSBpcyBub3QgTm9uZToKLSAgICAgICAgICAgIGFzc2VydCBpc2luc3RhbmNl
KGJvZHksIHN0ciksICdib2R5IG11c3QgYmUgYSBzdHInCi0gICAgICAgICAgICBieXRlcyA9IHNl
bGYuX2VuY29kZV9idWxrX2RhdGEoYm9keSkKLSAgICAgICAgICAgIHNlbGYuX3dyaXRlX2Z1bmMo
Ynl0ZXMpCi0KLSAgICBkZWYgbmV4dF9yZWFkX3NpemUoc2VsZik6Ci0gICAgICAgIGlmIHNlbGYu
X2ZpbmlzaGVkOgotICAgICAgICAgICAgcmV0dXJuIDAKLSAgICAgICAgaWYgc2VsZi5fYm9keV9k
ZWNvZGVyIGlzIE5vbmU6Ci0gICAgICAgICAgICByZXR1cm4gMQotICAgICAgICBlbHNlOgotICAg
ICAgICAgICAgcmV0dXJuIHNlbGYuX2JvZHlfZGVjb2Rlci5uZXh0X3JlYWRfc2l6ZSgpCi0KLQot
Y2xhc3MgTGVuZ3RoUHJlZml4ZWRCb2R5RGVjb2RlcihvYmplY3QpOgotICAgICIiIkRlY29kZXMg
dGhlIGxlbmd0aC1wcmVmaXhlZCBidWxrIGRhdGEuIiIiCi0gICAgCi0gICAgZGVmIF9faW5pdF9f
KHNlbGYpOgotICAgICAgICBzZWxmLmJ5dGVzX2xlZnQgPSBOb25lCi0gICAgICAgIHNlbGYuZmlu
aXNoZWRfcmVhZGluZyA9IEZhbHNlCi0gICAgICAgIHNlbGYudW51c2VkX2RhdGEgPSAnJwotICAg
ICAgICBzZWxmLnN0YXRlX2FjY2VwdCA9IHNlbGYuX3N0YXRlX2FjY2VwdF9leHBlY3RpbmdfbGVu
Z3RoCi0gICAgICAgIHNlbGYuc3RhdGVfcmVhZCA9IHNlbGYuX3N0YXRlX3JlYWRfbm9fZGF0YQot
ICAgICAgICBzZWxmLl9pbl9idWZmZXIgPSAnJwotICAgICAgICBzZWxmLl90cmFpbGVyX2J1ZmZl
ciA9ICcnCi0gICAgCi0gICAgZGVmIGFjY2VwdF9ieXRlcyhzZWxmLCBieXRlcyk6Ci0gICAgICAg
ICIiIkRlY29kZSBhcyBtdWNoIG9mIGJ5dGVzIGFzIHBvc3NpYmxlLgotCi0gICAgICAgIElmICdi
eXRlcycgY29udGFpbnMgdG9vIG11Y2ggZGF0YSBpdCB3aWxsIGJlIGFwcGVuZGVkIHRvCi0gICAg
ICAgIHNlbGYudW51c2VkX2RhdGEuCi0KLSAgICAgICAgZmluaXNoZWRfcmVhZGluZyB3aWxsIGJl
IHNldCB3aGVuIG5vIG1vcmUgZGF0YSBpcyByZXF1aXJlZC4gIEZ1cnRoZXIKLSAgICAgICAgZGF0
YSB3aWxsIGJlIGFwcGVuZGVkIHRvIHNlbGYudW51c2VkX2RhdGEuCi0gICAgICAgICIiIgotICAg
ICAgICAjIGFjY2VwdF9ieXRlcyBpcyBhbGxvd2VkIHRvIGNoYW5nZSB0aGUgc3RhdGUKLSAgICAg
ICAgY3VycmVudF9zdGF0ZSA9IHNlbGYuc3RhdGVfYWNjZXB0Ci0gICAgICAgIHNlbGYuc3RhdGVf
YWNjZXB0KGJ5dGVzKQotICAgICAgICB3aGlsZSBjdXJyZW50X3N0YXRlICE9IHNlbGYuc3RhdGVf
YWNjZXB0OgotICAgICAgICAgICAgY3VycmVudF9zdGF0ZSA9IHNlbGYuc3RhdGVfYWNjZXB0Ci0g
ICAgICAgICAgICBzZWxmLnN0YXRlX2FjY2VwdCgnJykKLQotICAgIGRlZiBuZXh0X3JlYWRfc2l6
ZShzZWxmKToKLSAgICAgICAgaWYgc2VsZi5ieXRlc19sZWZ0IGlzIG5vdCBOb25lOgotICAgICAg
ICAgICAgIyBJZGVhbGx5IHdlIHdhbnQgdG8gcmVhZCBhbGwgdGhlIHJlbWFpbmRlciBvZiB0aGUg
Ym9keSBhbmQgdGhlCi0gICAgICAgICAgICAjIHRyYWlsZXIgaW4gb25lIGdvLgotICAgICAgICAg
ICAgcmV0dXJuIHNlbGYuYnl0ZXNfbGVmdCArIDUKLSAgICAgICAgZWxpZiBzZWxmLnN0YXRlX2Fj
Y2VwdCA9PSBzZWxmLl9zdGF0ZV9hY2NlcHRfcmVhZGluZ190cmFpbGVyOgotICAgICAgICAgICAg
IyBKdXN0IHRoZSB0cmFpbGVyIGxlZnQKLSAgICAgICAgICAgIHJldHVybiA1IC0gbGVuKHNlbGYu
X3RyYWlsZXJfYnVmZmVyKQotICAgICAgICBlbGlmIHNlbGYuc3RhdGVfYWNjZXB0ID09IHNlbGYu
X3N0YXRlX2FjY2VwdF9leHBlY3RpbmdfbGVuZ3RoOgotICAgICAgICAgICAgIyBUaGVyZSdzIHN0
aWxsIGF0IGxlYXN0IDYgYnl0ZXMgbGVmdCAoJ1xuJyB0byBlbmQgdGhlIGxlbmd0aCwgcGx1cwot
ICAgICAgICAgICAgIyAnZG9uZVxuJykuCi0gICAgICAgICAgICByZXR1cm4gNgotICAgICAgICBl
bHNlOgotICAgICAgICAgICAgIyBSZWFkaW5nIGV4Y2VzcyBkYXRhLiAgRWl0aGVyIHdheSwgMSBi
eXRlIGF0IGEgdGltZSBpcyBmaW5lLgotICAgICAgICAgICAgcmV0dXJuIDEKLSAgICAgICAgCi0g
ICAgZGVmIHJlYWRfcGVuZGluZ19kYXRhKHNlbGYpOgotICAgICAgICAiIiJSZXR1cm4gYW55IHBl
bmRpbmcgZGF0YSB0aGF0IGhhcyBiZWVuIGRlY29kZWQuIiIiCi0gICAgICAgIHJldHVybiBzZWxm
LnN0YXRlX3JlYWQoKQotCi0gICAgZGVmIF9zdGF0ZV9hY2NlcHRfZXhwZWN0aW5nX2xlbmd0aChz
ZWxmLCBieXRlcyk6Ci0gICAgICAgIHNlbGYuX2luX2J1ZmZlciArPSBieXRlcwotICAgICAgICBw
b3MgPSBzZWxmLl9pbl9idWZmZXIuZmluZCgnXG4nKQotICAgICAgICBpZiBwb3MgPT0gLTE6Ci0g
ICAgICAgICAgICByZXR1cm4KLSAgICAgICAgc2VsZi5ieXRlc19sZWZ0ID0gaW50KHNlbGYuX2lu
X2J1ZmZlcls6cG9zXSkKLSAgICAgICAgc2VsZi5faW5fYnVmZmVyID0gc2VsZi5faW5fYnVmZmVy
W3BvcysxOl0KLSAgICAgICAgc2VsZi5ieXRlc19sZWZ0IC09IGxlbihzZWxmLl9pbl9idWZmZXIp
Ci0gICAgICAgIHNlbGYuc3RhdGVfYWNjZXB0ID0gc2VsZi5fc3RhdGVfYWNjZXB0X3JlYWRpbmdf
Ym9keQotICAgICAgICBzZWxmLnN0YXRlX3JlYWQgPSBzZWxmLl9zdGF0ZV9yZWFkX2luX2J1ZmZl
cgotCi0gICAgZGVmIF9zdGF0ZV9hY2NlcHRfcmVhZGluZ19ib2R5KHNlbGYsIGJ5dGVzKToKLSAg
ICAgICAgc2VsZi5faW5fYnVmZmVyICs9IGJ5dGVzCi0gICAgICAgIHNlbGYuYnl0ZXNfbGVmdCAt
PSBsZW4oYnl0ZXMpCi0gICAgICAgIGlmIHNlbGYuYnl0ZXNfbGVmdCA8PSAwOgotICAgICAgICAg
ICAgIyBGaW5pc2hlZCB3aXRoIGJvZHkKLSAgICAgICAgICAgIGlmIHNlbGYuYnl0ZXNfbGVmdCAh
PSAwOgotICAgICAgICAgICAgICAgIHNlbGYuX3RyYWlsZXJfYnVmZmVyID0gc2VsZi5faW5fYnVm
ZmVyW3NlbGYuYnl0ZXNfbGVmdDpdCi0gICAgICAgICAgICAgICAgc2VsZi5faW5fYnVmZmVyID0g
c2VsZi5faW5fYnVmZmVyWzpzZWxmLmJ5dGVzX2xlZnRdCi0gICAgICAgICAgICBzZWxmLmJ5dGVz
X2xlZnQgPSBOb25lCi0gICAgICAgICAgICBzZWxmLnN0YXRlX2FjY2VwdCA9IHNlbGYuX3N0YXRl
X2FjY2VwdF9yZWFkaW5nX3RyYWlsZXIKLSAgICAgICAgCi0gICAgZGVmIF9zdGF0ZV9hY2NlcHRf
cmVhZGluZ190cmFpbGVyKHNlbGYsIGJ5dGVzKToKLSAgICAgICAgc2VsZi5fdHJhaWxlcl9idWZm
ZXIgKz0gYnl0ZXMKLSAgICAgICAgIyBUT0RPOiB3aGF0IGlmIHRoZSB0cmFpbGVyIGRvZXMgbm90
IG1hdGNoICJkb25lXG4iPyAgU2hvdWxkIHRoaXMgcmFpc2UKLSAgICAgICAgIyBhIFByb3RvY29s
VmlvbGF0aW9uIGV4Y2VwdGlvbj8KLSAgICAgICAgaWYgc2VsZi5fdHJhaWxlcl9idWZmZXIuc3Rh
cnRzd2l0aCgnZG9uZVxuJyk6Ci0gICAgICAgICAgICBzZWxmLnVudXNlZF9kYXRhID0gc2VsZi5f
dHJhaWxlcl9idWZmZXJbbGVuKCdkb25lXG4nKTpdCi0gICAgICAgICAgICBzZWxmLnN0YXRlX2Fj
Y2VwdCA9IHNlbGYuX3N0YXRlX2FjY2VwdF9yZWFkaW5nX3VudXNlZAotICAgICAgICAgICAgc2Vs
Zi5maW5pc2hlZF9yZWFkaW5nID0gVHJ1ZQotICAgIAotICAgIGRlZiBfc3RhdGVfYWNjZXB0X3Jl
YWRpbmdfdW51c2VkKHNlbGYsIGJ5dGVzKToKLSAgICAgICAgc2VsZi51bnVzZWRfZGF0YSArPSBi
eXRlcwotCi0gICAgZGVmIF9zdGF0ZV9yZWFkX25vX2RhdGEoc2VsZik6Ci0gICAgICAgIHJldHVy
biAnJwotCi0gICAgZGVmIF9zdGF0ZV9yZWFkX2luX2J1ZmZlcihzZWxmKToKLSAgICAgICAgcmVz
dWx0ID0gc2VsZi5faW5fYnVmZmVyCi0gICAgICAgIHNlbGYuX2luX2J1ZmZlciA9ICcnCi0gICAg
ICAgIHJldHVybiByZXN1bHQKLQotCi1jbGFzcyBTbWFydFNlcnZlclN0cmVhbU1lZGl1bShvYmpl
Y3QpOgotICAgICIiIkhhbmRsZXMgc21hcnQgY29tbWFuZHMgY29taW5nIG92ZXIgYSBzdHJlYW0u
Ci0KLSAgICBUaGUgc3RyZWFtIG1heSBiZSBhIHBpcGUgY29ubmVjdGVkIHRvIHNzaGQsIG9yIGEg
dGNwIHNvY2tldCwgb3IgYW4KLSAgICBpbi1wcm9jZXNzIGZpZm8gZm9yIHRlc3RpbmcuCi0KLSAg
ICBPbmUgaW5zdGFuY2UgaXMgY3JlYXRlZCBmb3IgZWFjaCBjb25uZWN0ZWQgY2xpZW50OyBpdCBj
YW4gc2VydmUgbXVsdGlwbGUKLSAgICByZXF1ZXN0cyBpbiB0aGUgbGlmZXRpbWUgb2YgdGhlIGNv
bm5lY3Rpb24uCi0KLSAgICBUaGUgc2VydmVyIHBhc3NlcyByZXF1ZXN0cyB0aHJvdWdoIHRvIGFu
IHVuZGVybHlpbmcgYmFja2luZyB0cmFuc3BvcnQsIAotICAgIHdoaWNoIHdpbGwgdHlwaWNhbGx5
IGJlIGEgTG9jYWxUcmFuc3BvcnQgbG9va2luZyBhdCB0aGUgc2VydmVyJ3MgZmlsZXN5c3RlbS4K
LSAgICAiIiIKLQotICAgIGRlZiBfX2luaXRfXyhzZWxmLCBiYWNraW5nX3RyYW5zcG9ydCk6Ci0g
ICAgICAgICIiIkNvbnN0cnVjdCBuZXcgc2VydmVyLgotCi0gICAgICAgIDpwYXJhbSBiYWNraW5n
X3RyYW5zcG9ydDogVHJhbnNwb3J0IGZvciB0aGUgZGlyZWN0b3J5IHNlcnZlZC4KLSAgICAgICAg
IiIiCi0gICAgICAgICMgYmFja2luZ190cmFuc3BvcnQgY291bGQgYmUgcGFzc2VkIHRvIHNlcnZl
IGluc3RlYWQgb2YgX19pbml0X18KLSAgICAgICAgc2VsZi5iYWNraW5nX3RyYW5zcG9ydCA9IGJh
Y2tpbmdfdHJhbnNwb3J0Ci0gICAgICAgIHNlbGYuZmluaXNoZWQgPSBGYWxzZQotCi0gICAgZGVm
IHNlcnZlKHNlbGYpOgotICAgICAgICAiIiJTZXJ2ZSByZXF1ZXN0cyB1bnRpbCB0aGUgY2xpZW50
IGRpc2Nvbm5lY3RzLiIiIgotICAgICAgICAjIEtlZXAgYSByZWZlcmVuY2UgdG8gc3RkZXJyIGJl
Y2F1c2UgdGhlIHN5cyBtb2R1bGUncyBnbG9iYWxzIGdldCBzZXQgdG8KLSAgICAgICAgIyBOb25l
IGR1cmluZyBpbnRlcnByZXRlciBzaHV0ZG93bi4KLSAgICAgICAgZnJvbSBzeXMgaW1wb3J0IHN0
ZGVycgotICAgICAgICB0cnk6Ci0gICAgICAgICAgICB3aGlsZSBub3Qgc2VsZi5maW5pc2hlZDoK
LSAgICAgICAgICAgICAgICBwcm90b2NvbCA9IFNtYXJ0U2VydmVyUmVxdWVzdFByb3RvY29sT25l
KHNlbGYuYmFja2luZ190cmFuc3BvcnQsCi0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl93cml0ZV9vdXQpCi0gICAgICAgICAgICAg
ICAgc2VsZi5fc2VydmVfb25lX3JlcXVlc3QocHJvdG9jb2wpCi0gICAgICAgIGV4Y2VwdCBFeGNl
cHRpb24sIGU6Ci0gICAgICAgICAgICBzdGRlcnIud3JpdGUoIiVzIHRlcm1pbmF0aW5nIG9uIGV4
Y2VwdGlvbiAlc1xuIiAlIChzZWxmLCBlKSkKLSAgICAgICAgICAgIHJhaXNlCi0KLSAgICBkZWYg
X3NlcnZlX29uZV9yZXF1ZXN0KHNlbGYsIHByb3RvY29sKToKLSAgICAgICAgIiIiUmVhZCBvbmUg
cmVxdWVzdCBmcm9tIGlucHV0LCBwcm9jZXNzLCBzZW5kIGJhY2sgYSByZXNwb25zZS4KLSAgICAg
ICAgCi0gICAgICAgIDpwYXJhbSBwcm90b2NvbDogYSBTbWFydFNlcnZlclJlcXVlc3RQcm90b2Nv
bC4KLSAgICAgICAgIiIiCi0gICAgICAgIHRyeToKLSAgICAgICAgICAgIHNlbGYuX3NlcnZlX29u
ZV9yZXF1ZXN0X3VuZ3VhcmRlZChwcm90b2NvbCkKLSAgICAgICAgZXhjZXB0IEtleWJvYXJkSW50
ZXJydXB0OgotICAgICAgICAgICAgcmFpc2UKLSAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiwgZToK
LSAgICAgICAgICAgIHNlbGYudGVybWluYXRlX2R1ZV90b19lcnJvcigpCi0KLSAgICBkZWYgdGVy
bWluYXRlX2R1ZV90b19lcnJvcihzZWxmKToKLSAgICAgICAgIiIiQ2FsbGVkIHdoZW4gYW4gdW5o
YW5kbGVkIGV4Y2VwdGlvbiBmcm9tIHRoZSBwcm90b2NvbCBvY2N1cnMuIiIiCi0gICAgICAgIHJh
aXNlIE5vdEltcGxlbWVudGVkRXJyb3Ioc2VsZi50ZXJtaW5hdGVfZHVlX3RvX2Vycm9yKQotCi0K
LWNsYXNzIFNtYXJ0U2VydmVyU29ja2V0U3RyZWFtTWVkaXVtKFNtYXJ0U2VydmVyU3RyZWFtTWVk
aXVtKToKLQotICAgIGRlZiBfX2luaXRfXyhzZWxmLCBzb2NrLCBiYWNraW5nX3RyYW5zcG9ydCk6
Ci0gICAgICAgICIiIkNvbnN0cnVjdG9yLgotCi0gICAgICAgIDpwYXJhbSBzb2NrOiB0aGUgc29j
a2V0IHRoZSBzZXJ2ZXIgd2lsbCByZWFkIGZyb20uICBJdCB3aWxsIGJlIHB1dAotICAgICAgICAg
ICAgaW50byBibG9ja2luZyBtb2RlLgotICAgICAgICAiIiIKLSAgICAgICAgU21hcnRTZXJ2ZXJT
dHJlYW1NZWRpdW0uX19pbml0X18oc2VsZiwgYmFja2luZ190cmFuc3BvcnQpCi0gICAgICAgIHNl
bGYucHVzaF9iYWNrID0gJycKLSAgICAgICAgc29jay5zZXRibG9ja2luZyhUcnVlKQotICAgICAg
ICBzZWxmLnNvY2tldCA9IHNvY2sKLQotICAgIGRlZiBfc2VydmVfb25lX3JlcXVlc3RfdW5ndWFy
ZGVkKHNlbGYsIHByb3RvY29sKToKLSAgICAgICAgd2hpbGUgcHJvdG9jb2wubmV4dF9yZWFkX3Np
emUoKToKLSAgICAgICAgICAgIGlmIHNlbGYucHVzaF9iYWNrOgotICAgICAgICAgICAgICAgIHBy
b3RvY29sLmFjY2VwdF9ieXRlcyhzZWxmLnB1c2hfYmFjaykKLSAgICAgICAgICAgICAgICBzZWxm
LnB1c2hfYmFjayA9ICcnCi0gICAgICAgICAgICBlbHNlOgotICAgICAgICAgICAgICAgIGJ5dGVz
ID0gc2VsZi5zb2NrZXQucmVjdig0MDk2KQotICAgICAgICAgICAgICAgIGlmIGJ5dGVzID09ICcn
OgotICAgICAgICAgICAgICAgICAgICBzZWxmLmZpbmlzaGVkID0gVHJ1ZQotICAgICAgICAgICAg
ICAgICAgICByZXR1cm4KLSAgICAgICAgICAgICAgICBwcm90b2NvbC5hY2NlcHRfYnl0ZXMoYnl0
ZXMpCi0gICAgICAgIAotICAgICAgICBzZWxmLnB1c2hfYmFjayA9IHByb3RvY29sLmV4Y2Vzc19i
dWZmZXIKLSAgICAKLSAgICBkZWYgdGVybWluYXRlX2R1ZV90b19lcnJvcihzZWxmKToKLSAgICAg
ICAgIiIiQ2FsbGVkIHdoZW4gYW4gdW5oYW5kbGVkIGV4Y2VwdGlvbiBmcm9tIHRoZSBwcm90b2Nv
bCBvY2N1cnMuIiIiCi0gICAgICAgICMgVE9ETzogVGhpcyBzaG91bGQgbG9nIHRvIGEgc2VydmVy
IGxvZyBmaWxlLCBidXQgbm8gc3VjaCB0aGluZwotICAgICAgICAjIGV4aXN0cyB5ZXQuICBBbmRy
ZXcgQmVubmV0dHMgMjAwNi0wOS0yOS4KLSAgICAgICAgc2VsZi5zb2NrZXQuY2xvc2UoKQotICAg
ICAgICBzZWxmLmZpbmlzaGVkID0gVHJ1ZQotCi0gICAgZGVmIF93cml0ZV9vdXQoc2VsZiwgYnl0
ZXMpOgotICAgICAgICBzZWxmLnNvY2tldC5zZW5kYWxsKGJ5dGVzKQotCi0KLWNsYXNzIFNtYXJ0
U2VydmVyUGlwZVN0cmVhbU1lZGl1bShTbWFydFNlcnZlclN0cmVhbU1lZGl1bSk6Ci0KLSAgICBk
ZWYgX19pbml0X18oc2VsZiwgaW5fZmlsZSwgb3V0X2ZpbGUsIGJhY2tpbmdfdHJhbnNwb3J0KToK
LSAgICAgICAgIiIiQ29uc3RydWN0IG5ldyBzZXJ2ZXIuCi0KLSAgICAgICAgOnBhcmFtIGluX2Zp
bGU6IFB5dGhvbiBmaWxlIGZyb20gd2hpY2ggcmVxdWVzdHMgY2FuIGJlIHJlYWQuCi0gICAgICAg
IDpwYXJhbSBvdXRfZmlsZTogUHl0aG9uIGZpbGUgdG8gd3JpdGUgcmVzcG9uc2VzLgotICAgICAg
ICA6cGFyYW0gYmFja2luZ190cmFuc3BvcnQ6IFRyYW5zcG9ydCBmb3IgdGhlIGRpcmVjdG9yeSBz
ZXJ2ZWQuCi0gICAgICAgICIiIgotICAgICAgICBTbWFydFNlcnZlclN0cmVhbU1lZGl1bS5fX2lu
aXRfXyhzZWxmLCBiYWNraW5nX3RyYW5zcG9ydCkKLSAgICAgICAgaWYgc3lzLnBsYXRmb3JtID09
ICd3aW4zMic6Ci0gICAgICAgICAgICAjIGZvcmNlIGJpbmFyeSBtb2RlIGZvciBmaWxlcwotICAg
ICAgICAgICAgaW1wb3J0IG1zdmNydAotICAgICAgICAgICAgZm9yIGYgaW4gKGluX2ZpbGUsIG91
dF9maWxlKToKLSAgICAgICAgICAgICAgICBmaWxlbm8gPSBnZXRhdHRyKGYsICdmaWxlbm8nLCBO
b25lKQotICAgICAgICAgICAgICAgIGlmIGZpbGVubzoKLSAgICAgICAgICAgICAgICAgICAgbXN2
Y3J0LnNldG1vZGUoZmlsZW5vKCksIG9zLk9fQklOQVJZKQotICAgICAgICBzZWxmLl9pbiA9IGlu
X2ZpbGUKLSAgICAgICAgc2VsZi5fb3V0ID0gb3V0X2ZpbGUKLQotICAgIGRlZiBfc2VydmVfb25l
X3JlcXVlc3RfdW5ndWFyZGVkKHNlbGYsIHByb3RvY29sKToKLSAgICAgICAgd2hpbGUgVHJ1ZToK
LSAgICAgICAgICAgIGJ5dGVzX3RvX3JlYWQgPSBwcm90b2NvbC5uZXh0X3JlYWRfc2l6ZSgpCi0g
ICAgICAgICAgICBpZiBieXRlc190b19yZWFkID09IDA6Ci0gICAgICAgICAgICAgICAgIyBGaW5p
c2hlZCBzZXJ2aW5nIHRoaXMgcmVxdWVzdC4KLSAgICAgICAgICAgICAgICBzZWxmLl9vdXQuZmx1
c2goKQotICAgICAgICAgICAgICAgIHJldHVybgotICAgICAgICAgICAgYnl0ZXMgPSBzZWxmLl9p
bi5yZWFkKGJ5dGVzX3RvX3JlYWQpCi0gICAgICAgICAgICBpZiBieXRlcyA9PSAnJzoKLSAgICAg
ICAgICAgICAgICAjIENvbm5lY3Rpb24gaGFzIGJlZW4gY2xvc2VkLgotICAgICAgICAgICAgICAg
IHNlbGYuZmluaXNoZWQgPSBUcnVlCi0gICAgICAgICAgICAgICAgc2VsZi5fb3V0LmZsdXNoKCkK
LSAgICAgICAgICAgICAgICByZXR1cm4KLSAgICAgICAgICAgIHByb3RvY29sLmFjY2VwdF9ieXRl
cyhieXRlcykKLQotICAgIGRlZiB0ZXJtaW5hdGVfZHVlX3RvX2Vycm9yKHNlbGYpOgotICAgICAg
ICAjIFRPRE86IFRoaXMgc2hvdWxkIGxvZyB0byBhIHNlcnZlciBsb2cgZmlsZSwgYnV0IG5vIHN1
Y2ggdGhpbmcKLSAgICAgICAgIyBleGlzdHMgeWV0LiAgQW5kcmV3IEJlbm5ldHRzIDIwMDYtMDkt
MjkuCi0gICAgICAgIHNlbGYuX291dC5jbG9zZSgpCi0gICAgICAgIHNlbGYuZmluaXNoZWQgPSBU
cnVlCi0KLSAgICBkZWYgX3dyaXRlX291dChzZWxmLCBieXRlcyk6Ci0gICAgICAgIHNlbGYuX291
dC53cml0ZShieXRlcykKLQotCi1jbGFzcyBTbWFydFNlcnZlclJlc3BvbnNlKG9iamVjdCk6Ci0g
ICAgIiIiUmVzcG9uc2UgZ2VuZXJhdGVkIGJ5IFNtYXJ0U2VydmVyUmVxdWVzdEhhbmRsZXIuIiIi
Ci0KLSAgICBkZWYgX19pbml0X18oc2VsZiwgYXJncywgYm9keT1Ob25lKToKLSAgICAgICAgc2Vs
Zi5hcmdzID0gYXJncwotICAgICAgICBzZWxmLmJvZHkgPSBib2R5Ci0KLSMgWFhYOiBUT0RPOiBD
cmVhdGUgYSBTbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyIHdoaWNoIHdpbGwgdGFrZSB0aGUgcmVz
cG9uc2liaWxpdHkKLSMgZm9yIGRlbGl2ZXJpbmcgdGhlIGRhdGEgZm9yIGEgcmVxdWVzdC4gVGhp
cyBjb3VsZCBiZSBkb25lIHdpdGggYXMgdGhlCi0jIFN0cmVhbVNlcnZlciwgdGhvdWdoIHRoYXQg
d291bGQgY3JlYXRlIGNvbmZsYXRpb24gYmV0d2VlbiByZXF1ZXN0IGFuZCByZXNwb25zZQotIyB3
aGljaCBtYXkgYmUgdW5kZXNpcmFibGUuCi0KLQotY2xhc3MgU21hcnRTZXJ2ZXJSZXF1ZXN0SGFu
ZGxlcihvYmplY3QpOgotICAgICIiIlByb3RvY29sIGxvZ2ljIGZvciBzbWFydCBzZXJ2ZXIuCi0g
ICAgCi0gICAgVGhpcyBkb2Vzbid0IGhhbmRsZSBzZXJpYWxpemF0aW9uIGF0IGFsbCwgaXQganVz
dCBwcm9jZXNzZXMgcmVxdWVzdHMgYW5kCi0gICAgY3JlYXRlcyByZXNwb25zZXMuCi0gICAgIiIi
Ci0KLSAgICAjIElNUE9SVEFOVCBGT1IgSU1QTEVNRU5UT1JTOiBJdCBpcyBpbXBvcnRhbnQgdGhh
dCBTbWFydFNlcnZlclJlcXVlc3RIYW5kbGVyCi0gICAgIyBub3QgY29udGFpbiBlbmNvZGluZyBv
ciBkZWNvZGluZyBsb2dpYyB0byBhbGxvdyB0aGUgd2lyZSBwcm90b2NvbCB0byB2YXJ5Ci0gICAg
IyBmcm9tIHRoZSBvYmplY3QgcHJvdG9jb2w6IHdlIHdpbGwgd2FudCB0byB0d2VhayB0aGUgd2ly
ZSBwcm90b2NvbCBzZXBhcmF0ZQotICAgICMgZnJvbSB0aGUgb2JqZWN0IG1vZGVsLCBhbmQgaWRl
YWxseSB3ZSB3aWxsIGJlIGFibGUgdG8gZG8gdGhhdCB3aXRob3V0Ci0gICAgIyBoYXZpbmcgYSBT
bWFydFNlcnZlclJlcXVlc3RIYW5kbGVyIHN1YmNsYXNzIGZvciBlYWNoIHdpcmUgcHJvdG9jb2ws
IHJhdGhlcgotICAgICMganVzdCBhIFByb3RvY29sIHN1YmNsYXNzLgotCi0gICAgIyBUT0RPOiBC
ZXR0ZXIgd2F5IG9mIHJlcHJlc2VudGluZyB0aGUgYm9keSBmb3IgY29tbWFuZHMgdGhhdCB0YWtl
IGl0LAotICAgICMgYW5kIGFsbG93IGl0IHRvIGJlIHN0cmVhbWVkIGludG8gdGhlIHNlcnZlci4K
LSAgICAKLSAgICBkZWYgX19pbml0X18oc2VsZiwgYmFja2luZ190cmFuc3BvcnQpOgotICAgICAg
ICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydCA9IGJhY2tpbmdfdHJhbnNwb3J0Ci0gICAgICAgIHNl
bGYuX2NvbnZlcnRlZF9jb21tYW5kID0gRmFsc2UKLSAgICAgICAgc2VsZi5maW5pc2hlZF9yZWFk
aW5nID0gRmFsc2UKLSAgICAgICAgc2VsZi5fYm9keV9ieXRlcyA9ICcnCi0gICAgICAgIHNlbGYu
cmVzcG9uc2UgPSBOb25lCi0KLSAgICBkZWYgYWNjZXB0X2JvZHkoc2VsZiwgYnl0ZXMpOgotICAg
ICAgICAiIiJBY2NlcHQgYm9keSBkYXRhLgotCi0gICAgICAgIFRoaXMgc2hvdWxkIGJlIG92ZXJy
aWRlbiBmb3IgZWFjaCBjb21tYW5kIHRoYXQgZGVzaXJlZCBib2R5IGRhdGEgdG8KLSAgICAgICAg
aGFuZGxlIHRoZSByaWdodCBmb3JtYXQgb2YgdGhhdCBkYXRhLiBJLmUuIHBsYWluIGJ5dGVzLCBh
IGJ1bmRsZSBldGMuCi0KLSAgICAgICAgVGhlIGRlc2VyaWFsaXNhdGlvbiBpbnRvIHRoYXQgZm9y
bWF0IHNob3VsZCBiZSBkb25lIGluIHRoZSBQcm90b2NvbAotICAgICAgICBvYmplY3QuIFNldCBz
ZWxmLmRlc2lyZWRfYm9keV9mb3JtYXQgdG8gdGhlIGZvcm1hdCB5b3VyIG1ldGhvZCB3aWxsCi0g
ICAgICAgIGhhbmRsZS4KLSAgICAgICAgIiIiCi0gICAgICAgICMgZGVmYXVsdCBmYWxsYmFjayBp
cyB0byBhY2N1bXVsYXRlIGJ5dGVzLgotICAgICAgICBzZWxmLl9ib2R5X2J5dGVzICs9IGJ5dGVz
Ci0gICAgICAgIAotICAgIGRlZiBfZW5kX29mX2JvZHlfaGFuZGxlcihzZWxmKToKLSAgICAgICAg
IiIiQW4gdW5pbXBsZW1lbnRlZCBlbmQgb2YgYm9keSBoYW5kbGVyLiIiIgotICAgICAgICByYWlz
ZSBOb3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuX2VuZF9vZl9ib2R5X2hhbmRsZXIpCi0gICAgICAg
IAotICAgIGRlZiBkb19oZWxsbyhzZWxmKToKLSAgICAgICAgIiIiQW5zd2VyIGEgdmVyc2lvbiBy
ZXF1ZXN0IHdpdGggbXkgdmVyc2lvbi4iIiIKLSAgICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVz
cG9uc2UoKCdvaycsICcxJykpCi0KLSAgICBkZWYgZG9faGFzKHNlbGYsIHJlbHBhdGgpOgotICAg
ICAgICByID0gc2VsZi5fYmFja2luZ190cmFuc3BvcnQuaGFzKHJlbHBhdGgpIGFuZCAneWVzJyBv
ciAnbm8nCi0gICAgICAgIHJldHVybiBTbWFydFNlcnZlclJlc3BvbnNlKChyLCkpCi0KLSAgICBk
ZWYgZG9fZ2V0KHNlbGYsIHJlbHBhdGgpOgotICAgICAgICBiYWNraW5nX2J5dGVzID0gc2VsZi5f
YmFja2luZ190cmFuc3BvcnQuZ2V0X2J5dGVzKHJlbHBhdGgpCi0gICAgICAgIHJldHVybiBTbWFy
dFNlcnZlclJlc3BvbnNlKCgnb2snLCksIGJhY2tpbmdfYnl0ZXMpCi0KLSAgICBkZWYgX2Rlc2Vy
aWFsaXNlX29wdGlvbmFsX21vZGUoc2VsZiwgbW9kZSk6Ci0gICAgICAgICMgWFhYOiBGSVhNRSB0
aGlzIHNob3VsZCBiZSBvbiB0aGUgcHJvdG9jb2wgb2JqZWN0LgotICAgICAgICBpZiBtb2RlID09
ICcnOgotICAgICAgICAgICAgcmV0dXJuIE5vbmUKLSAgICAgICAgZWxzZToKLSAgICAgICAgICAg
IHJldHVybiBpbnQobW9kZSkKLQotICAgIGRlZiBkb19hcHBlbmQoc2VsZiwgcmVscGF0aCwgbW9k
ZSk6Ci0gICAgICAgIHNlbGYuX2NvbnZlcnRlZF9jb21tYW5kID0gVHJ1ZQotICAgICAgICBzZWxm
Ll9yZWxwYXRoID0gcmVscGF0aAotICAgICAgICBzZWxmLl9tb2RlID0gc2VsZi5fZGVzZXJpYWxp
c2Vfb3B0aW9uYWxfbW9kZShtb2RlKQotICAgICAgICBzZWxmLl9lbmRfb2ZfYm9keV9oYW5kbGVy
ID0gc2VsZi5faGFuZGxlX2RvX2FwcGVuZF9lbmQKLSAgICAKLSAgICBkZWYgX2hhbmRsZV9kb19h
cHBlbmRfZW5kKHNlbGYpOgotICAgICAgICBvbGRfbGVuZ3RoID0gc2VsZi5fYmFja2luZ190cmFu
c3BvcnQuYXBwZW5kX2J5dGVzKAotICAgICAgICAgICAgc2VsZi5fcmVscGF0aCwgc2VsZi5fYm9k
eV9ieXRlcywgc2VsZi5fbW9kZSkKLSAgICAgICAgc2VsZi5yZXNwb25zZSA9IFNtYXJ0U2VydmVy
UmVzcG9uc2UoKCdhcHBlbmRlZCcsICclZCcgJSBvbGRfbGVuZ3RoKSkKLQotICAgIGRlZiBkb19k
ZWxldGUoc2VsZiwgcmVscGF0aCk6Ci0gICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LmRl
bGV0ZShyZWxwYXRoKQotCi0gICAgZGVmIGRvX2l0ZXJfZmlsZXNfcmVjdXJzaXZlKHNlbGYsIHJl
bHBhdGgpOgotICAgICAgICB0cmFuc3BvcnQgPSBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5jbG9u
ZShyZWxwYXRoKQotICAgICAgICBmaWxlbmFtZXMgPSB0cmFuc3BvcnQuaXRlcl9maWxlc19yZWN1
cnNpdmUoKQotICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ25hbWVzJywpICsg
dHVwbGUoZmlsZW5hbWVzKSkKLQotICAgIGRlZiBkb19saXN0X2RpcihzZWxmLCByZWxwYXRoKToK
LSAgICAgICAgZmlsZW5hbWVzID0gc2VsZi5fYmFja2luZ190cmFuc3BvcnQubGlzdF9kaXIocmVs
cGF0aCkKLSAgICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVzcG9uc2UoKCduYW1lcycsKSArIHR1
cGxlKGZpbGVuYW1lcykpCi0KLSAgICBkZWYgZG9fbWtkaXIoc2VsZiwgcmVscGF0aCwgbW9kZSk6
Ci0gICAgICAgIHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0Lm1rZGlyKHJlbHBhdGgsCi0gICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2Rlc2VyaWFsaXNlX29wdGlvbmFs
X21vZGUobW9kZSkpCi0KLSAgICBkZWYgZG9fbW92ZShzZWxmLCByZWxfZnJvbSwgcmVsX3RvKToK
LSAgICAgICAgc2VsZi5fYmFja2luZ190cmFuc3BvcnQubW92ZShyZWxfZnJvbSwgcmVsX3RvKQot
Ci0gICAgZGVmIGRvX3B1dChzZWxmLCByZWxwYXRoLCBtb2RlKToKLSAgICAgICAgc2VsZi5fY29u
dmVydGVkX2NvbW1hbmQgPSBUcnVlCi0gICAgICAgIHNlbGYuX3JlbHBhdGggPSByZWxwYXRoCi0g
ICAgICAgIHNlbGYuX21vZGUgPSBzZWxmLl9kZXNlcmlhbGlzZV9vcHRpb25hbF9tb2RlKG1vZGUp
Ci0gICAgICAgIHNlbGYuX2VuZF9vZl9ib2R5X2hhbmRsZXIgPSBzZWxmLl9oYW5kbGVfZG9fcHV0
Ci0KLSAgICBkZWYgX2hhbmRsZV9kb19wdXQoc2VsZik6Ci0gICAgICAgIHNlbGYuX2JhY2tpbmdf
dHJhbnNwb3J0LnB1dF9ieXRlcyhzZWxmLl9yZWxwYXRoLAotICAgICAgICAgICAgICAgIHNlbGYu
X2JvZHlfYnl0ZXMsIHNlbGYuX21vZGUpCi0gICAgICAgIHNlbGYucmVzcG9uc2UgPSBTbWFydFNl
cnZlclJlc3BvbnNlKCgnb2snLCkpCi0KLSAgICBkZWYgX2Rlc2VyaWFsaXNlX29mZnNldHMoc2Vs
ZiwgdGV4dCk6Ci0gICAgICAgICMgWFhYOiBGSVhNRSB0aGlzIHNob3VsZCBiZSBvbiB0aGUgcHJv
dG9jb2wgb2JqZWN0LgotICAgICAgICBvZmZzZXRzID0gW10KLSAgICAgICAgZm9yIGxpbmUgaW4g
dGV4dC5zcGxpdCgnXG4nKToKLSAgICAgICAgICAgIGlmIG5vdCBsaW5lOgotICAgICAgICAgICAg
ICAgIGNvbnRpbnVlCi0gICAgICAgICAgICBzdGFydCwgbGVuZ3RoID0gbGluZS5zcGxpdCgnLCcp
Ci0gICAgICAgICAgICBvZmZzZXRzLmFwcGVuZCgoaW50KHN0YXJ0KSwgaW50KGxlbmd0aCkpKQot
ICAgICAgICByZXR1cm4gb2Zmc2V0cwotCi0gICAgZGVmIGRvX3B1dF9ub25fYXRvbWljKHNlbGYs
IHJlbHBhdGgsIG1vZGUsIGNyZWF0ZV9wYXJlbnQsIGRpcl9tb2RlKToKLSAgICAgICAgc2VsZi5f
Y29udmVydGVkX2NvbW1hbmQgPSBUcnVlCi0gICAgICAgIHNlbGYuX2VuZF9vZl9ib2R5X2hhbmRs
ZXIgPSBzZWxmLl9oYW5kbGVfcHV0X25vbl9hdG9taWMKLSAgICAgICAgc2VsZi5fcmVscGF0aCA9
IHJlbHBhdGgKLSAgICAgICAgc2VsZi5fZGlyX21vZGUgPSBzZWxmLl9kZXNlcmlhbGlzZV9vcHRp
b25hbF9tb2RlKGRpcl9tb2RlKQotICAgICAgICBzZWxmLl9tb2RlID0gc2VsZi5fZGVzZXJpYWxp
c2Vfb3B0aW9uYWxfbW9kZShtb2RlKQotICAgICAgICAjIGEgYm9vbGVhbiB3b3VsZCBiZSBuaWNl
ciBYWFgKLSAgICAgICAgc2VsZi5fY3JlYXRlX3BhcmVudCA9IChjcmVhdGVfcGFyZW50ID09ICdU
JykKLQotICAgIGRlZiBfaGFuZGxlX3B1dF9ub25fYXRvbWljKHNlbGYpOgotICAgICAgICBzZWxm
Ll9iYWNraW5nX3RyYW5zcG9ydC5wdXRfYnl0ZXNfbm9uX2F0b21pYyhzZWxmLl9yZWxwYXRoLAot
ICAgICAgICAgICAgICAgIHNlbGYuX2JvZHlfYnl0ZXMsCi0gICAgICAgICAgICAgICAgbW9kZT1z
ZWxmLl9tb2RlLAotICAgICAgICAgICAgICAgIGNyZWF0ZV9wYXJlbnRfZGlyPXNlbGYuX2NyZWF0
ZV9wYXJlbnQsCi0gICAgICAgICAgICAgICAgZGlyX21vZGU9c2VsZi5fZGlyX21vZGUpCi0gICAg
ICAgIHNlbGYucmVzcG9uc2UgPSBTbWFydFNlcnZlclJlc3BvbnNlKCgnb2snLCkpCi0KLSAgICBk
ZWYgZG9fcmVhZHYoc2VsZiwgcmVscGF0aCk6Ci0gICAgICAgIHNlbGYuX2NvbnZlcnRlZF9jb21t
YW5kID0gVHJ1ZQotICAgICAgICBzZWxmLl9lbmRfb2ZfYm9keV9oYW5kbGVyID0gc2VsZi5faGFu
ZGxlX3JlYWR2X29mZnNldHMKLSAgICAgICAgc2VsZi5fcmVscGF0aCA9IHJlbHBhdGgKLQotICAg
IGRlZiBlbmRfb2ZfYm9keShzZWxmKToKLSAgICAgICAgIiIiTm8gbW9yZSBib2R5IGRhdGEgd2ls
bCBiZSByZWNlaXZlZC4iIiIKLSAgICAgICAgc2VsZi5fcnVuX2hhbmRsZXJfY29kZShzZWxmLl9l
bmRfb2ZfYm9keV9oYW5kbGVyLCAoKSwge30pCi0gICAgICAgICMgY2Fubm90IHJlYWQgYWZ0ZXIg
dGhpcy4KLSAgICAgICAgc2VsZi5maW5pc2hlZF9yZWFkaW5nID0gVHJ1ZQotCi0gICAgZGVmIF9o
YW5kbGVfcmVhZHZfb2Zmc2V0cyhzZWxmKToKLSAgICAgICAgIiIiYWNjZXB0IG9mZnNldHMgZm9y
IGEgcmVhZHYgcmVxdWVzdC4iIiIKLSAgICAgICAgb2Zmc2V0cyA9IHNlbGYuX2Rlc2VyaWFsaXNl
X29mZnNldHMoc2VsZi5fYm9keV9ieXRlcykKLSAgICAgICAgYmFja2luZ19ieXRlcyA9ICcnLmpv
aW4oYnl0ZXMgZm9yIG9mZnNldCwgYnl0ZXMgaW4KLSAgICAgICAgICAgIHNlbGYuX2JhY2tpbmdf
dHJhbnNwb3J0LnJlYWR2KHNlbGYuX3JlbHBhdGgsIG9mZnNldHMpKQotICAgICAgICBzZWxmLnJl
c3BvbnNlID0gU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ3JlYWR2JywpLCBiYWNraW5nX2J5dGVzKQot
ICAgICAgICAKLSAgICBkZWYgZG9fcmVuYW1lKHNlbGYsIHJlbF9mcm9tLCByZWxfdG8pOgotICAg
ICAgICBzZWxmLl9iYWNraW5nX3RyYW5zcG9ydC5yZW5hbWUocmVsX2Zyb20sIHJlbF90bykKLQot
ICAgIGRlZiBkb19ybWRpcihzZWxmLCByZWxwYXRoKToKLSAgICAgICAgc2VsZi5fYmFja2luZ190
cmFuc3BvcnQucm1kaXIocmVscGF0aCkKLQotICAgIGRlZiBkb19zdGF0KHNlbGYsIHJlbHBhdGgp
OgotICAgICAgICBzdGF0ID0gc2VsZi5fYmFja2luZ190cmFuc3BvcnQuc3RhdChyZWxwYXRoKQot
ICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ3N0YXQnLCBzdHIoc3RhdC5zdF9z
aXplKSwgb2N0KHN0YXQuc3RfbW9kZSkpKQotICAgICAgICAKLSAgICBkZWYgZG9fZ2V0X2J1bmRs
ZShzZWxmLCBwYXRoLCByZXZpc2lvbl9pZCk6Ci0gICAgICAgICMgb3BlbiB0cmFuc3BvcnQgcmVs
YXRpdmUgdG8gb3VyIGJhc2UKLSAgICAgICAgdCA9IHNlbGYuX2JhY2tpbmdfdHJhbnNwb3J0LmNs
b25lKHBhdGgpCi0gICAgICAgIGNvbnRyb2wsIGV4dHJhX3BhdGggPSBienJkaXIuQnpyRGlyLm9w
ZW5fY29udGFpbmluZ19mcm9tX3RyYW5zcG9ydCh0KQotICAgICAgICByZXBvID0gY29udHJvbC5v
cGVuX3JlcG9zaXRvcnkoKQotICAgICAgICB0bXBmID0gdGVtcGZpbGUuVGVtcG9yYXJ5RmlsZSgp
Ci0gICAgICAgIGJhc2VfcmV2aXNpb24gPSByZXZpc2lvbi5OVUxMX1JFVklTSU9OCi0gICAgICAg
IHdyaXRlX2J1bmRsZShyZXBvLCByZXZpc2lvbl9pZCwgYmFzZV9yZXZpc2lvbiwgdG1wZikKLSAg
ICAgICAgdG1wZi5zZWVrKDApCi0gICAgICAgIHJldHVybiBTbWFydFNlcnZlclJlc3BvbnNlKCgp
LCB0bXBmLnJlYWQoKSkKLQotICAgIGRlZiBkaXNwYXRjaF9jb21tYW5kKHNlbGYsIGNtZCwgYXJn
cyk6Ci0gICAgICAgICIiIkRlcHJlY2F0ZWQgY29tcGF0aWJpbGl0eSBtZXRob2QuIiIiICMgWFhY
IFhYWAotICAgICAgICBmdW5jID0gZ2V0YXR0cihzZWxmLCAnZG9fJyArIGNtZCwgTm9uZSkKLSAg
ICAgICAgaWYgZnVuYyBpcyBOb25lOgotICAgICAgICAgICAgcmFpc2UgZXJyb3JzLlNtYXJ0UHJv
dG9jb2xFcnJvcigiYmFkIHJlcXVlc3QgJXIiICUgKGNtZCwpKQotICAgICAgICBzZWxmLl9ydW5f
aGFuZGxlcl9jb2RlKGZ1bmMsIGFyZ3MsIHt9KQotCi0gICAgZGVmIF9ydW5faGFuZGxlcl9jb2Rl
KHNlbGYsIGNhbGxhYmxlLCBhcmdzLCBrd2FyZ3MpOgotICAgICAgICAiIiJSdW4gc29tZSBoYW5k
bGVyIHNwZWNpZmljIGNvZGUgJ2NhbGxhYmxlJy4KLQotICAgICAgICBJZiBhIHJlc3VsdCBpcyBy
ZXR1cm5lZCwgaXQgaXMgY29uc2lkZXJlZCB0byBiZSB0aGUgY29tbWFuZHMgcmVzcG9uc2UsCi0g
ICAgICAgIGFuZCBmaW5pc2hlZF9yZWFkaW5nIGlzIHNldCB0cnVlLCBhbmQgaXRzIGFzc2lnbmVk
IHRvIHNlbGYucmVzcG9uc2UuCi0KLSAgICAgICAgQW55IGV4Y2VwdGlvbnMgY2F1Z2h0IGFyZSB0
cmFuc2xhdGVkIGFuZCBhIHJlc3BvbnNlIG9iamVjdCBjcmVhdGVkCi0gICAgICAgIGZyb20gdGhl
bS4KLSAgICAgICAgIiIiCi0gICAgICAgIHJlc3VsdCA9IHNlbGYuX2NhbGxfY29udmVydGluZ19l
cnJvcnMoY2FsbGFibGUsIGFyZ3MsIGt3YXJncykKLSAgICAgICAgaWYgcmVzdWx0IGlzIG5vdCBO
b25lOgotICAgICAgICAgICAgc2VsZi5yZXNwb25zZSA9IHJlc3VsdAotICAgICAgICAgICAgc2Vs
Zi5maW5pc2hlZF9yZWFkaW5nID0gVHJ1ZQotICAgICAgICAjIGhhbmRsZSB1bmNvbnZlcnRlZCBj
b21tYW5kcwotICAgICAgICBpZiBub3Qgc2VsZi5fY29udmVydGVkX2NvbW1hbmQ6Ci0gICAgICAg
ICAgICBzZWxmLmZpbmlzaGVkX3JlYWRpbmcgPSBUcnVlCi0gICAgICAgICAgICBpZiByZXN1bHQg
aXMgTm9uZToKLSAgICAgICAgICAgICAgICBzZWxmLnJlc3BvbnNlID0gU21hcnRTZXJ2ZXJSZXNw
b25zZSgoJ29rJywpKQotCi0gICAgZGVmIF9jYWxsX2NvbnZlcnRpbmdfZXJyb3JzKHNlbGYsIGNh
bGxhYmxlLCBhcmdzLCBrd2FyZ3MpOgotICAgICAgICAiIiJDYWxsIGNhbGxhYmxlIGNvbnZlcnRp
bmcgZXJyb3JzIHRvIFJlc3BvbnNlIG9iamVjdHMuIiIiCi0gICAgICAgIHRyeToKLSAgICAgICAg
ICAgIHJldHVybiBjYWxsYWJsZSgqYXJncywgKiprd2FyZ3MpCi0gICAgICAgIGV4Y2VwdCBlcnJv
cnMuTm9TdWNoRmlsZSwgZToKLSAgICAgICAgICAgIHJldHVybiBTbWFydFNlcnZlclJlc3BvbnNl
KCgnTm9TdWNoRmlsZScsIGUucGF0aCkpCi0gICAgICAgIGV4Y2VwdCBlcnJvcnMuRmlsZUV4aXN0
cywgZToKLSAgICAgICAgICAgIHJldHVybiBTbWFydFNlcnZlclJlc3BvbnNlKCgnRmlsZUV4aXN0
cycsIGUucGF0aCkpCi0gICAgICAgIGV4Y2VwdCBlcnJvcnMuRGlyZWN0b3J5Tm90RW1wdHksIGU6
Ci0gICAgICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ0RpcmVjdG9yeU5vdEVt
cHR5JywgZS5wYXRoKSkKLSAgICAgICAgZXhjZXB0IGVycm9ycy5TaG9ydFJlYWR2RXJyb3IsIGU6
Ci0gICAgICAgICAgICByZXR1cm4gU21hcnRTZXJ2ZXJSZXNwb25zZSgoJ1Nob3J0UmVhZHZFcnJv
cicsCi0gICAgICAgICAgICAgICAgZS5wYXRoLCBzdHIoZS5vZmZzZXQpLCBzdHIoZS5sZW5ndGgp
LCBzdHIoZS5hY3R1YWwpKSkKLSAgICAgICAgZXhjZXB0IFVuaWNvZGVFcnJvciwgZToKLSAgICAg
ICAgICAgICMgSWYgaXQgaXMgYSBEZWNvZGVFcnJvciwgdGhhbiBtb3N0IGxpa2VseSB3ZSBhcmUg
c3RhcnRpbmcKLSAgICAgICAgICAgICMgd2l0aCBhIHBsYWluIHN0cmluZwotICAgICAgICAgICAg
c3RyX29yX3VuaWNvZGUgPSBlLm9iamVjdAotICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShzdHJf
b3JfdW5pY29kZSwgdW5pY29kZSk6Ci0gICAgICAgICAgICAgICAgIyBYWFg6IFVURi04IG1pZ2h0
IGhhdmUgXHgwMSAob3VyIHNlcGVyYXRvciBieXRlKSBpbiBpdC4gIFdlCi0gICAgICAgICAgICAg
ICAgIyBzaG91bGQgZXNjYXBlIGl0IHNvbWVob3cuCi0gICAgICAgICAgICAgICAgdmFsID0gJ3U6
JyArIHN0cl9vcl91bmljb2RlLmVuY29kZSgndXRmLTgnKQotICAgICAgICAgICAgZWxzZToKLSAg
ICAgICAgICAgICAgICB2YWwgPSAnczonICsgc3RyX29yX3VuaWNvZGUuZW5jb2RlKCdiYXNlNjQn
KQotICAgICAgICAgICAgIyBUaGlzIGhhbmRsZXMgVW5pY29kZUVuY29kZUVycm9yIG9yIFVuaWNv
ZGVEZWNvZGVFcnJvcgotICAgICAgICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVzcG9uc2UoKGUu
X19jbGFzc19fLl9fbmFtZV9fLAotICAgICAgICAgICAgICAgICAgICBlLmVuY29kaW5nLCB2YWws
IHN0cihlLnN0YXJ0KSwgc3RyKGUuZW5kKSwgZS5yZWFzb24pKQotICAgICAgICBleGNlcHQgZXJy
b3JzLlRyYW5zcG9ydE5vdFBvc3NpYmxlLCBlOgotICAgICAgICAgICAgaWYgZS5tc2cgPT0gInJl
YWRvbmx5IHRyYW5zcG9ydCI6Ci0gICAgICAgICAgICAgICAgcmV0dXJuIFNtYXJ0U2VydmVyUmVz
cG9uc2UoKCdSZWFkT25seUVycm9yJywgKSkKLSAgICAgICAgICAgIGVsc2U6Ci0gICAgICAgICAg
ICAgICAgcmFpc2UKLQotCiBjbGFzcyBTbWFydFN0YXQob2JqZWN0KToKIAogICAgIGRlZiBfX2lu
aXRfXyhzZWxmLCBzaXplLCBtb2RlKToKQEAgLTEwMDIsNDU1ICszOTgsNiBAQAogICAgICAgICAg
ICAgc2VsZi5fdHJhbnNsYXRlX2Vycm9yKHJlc3ApCiAKIAotY2xhc3MgU21hcnRDbGllbnRNZWRp
dW1SZXF1ZXN0KG9iamVjdCk6Ci0gICAgIiIiQSByZXF1ZXN0IG9uIGEgU21hcnRDbGllbnRNZWRp
dW0uCi0KLSAgICBFYWNoIHJlcXVlc3QgYWxsb3dzIGJ5dGVzIHRvIGJlIHByb3ZpZGVkIHRvIGl0
IHZpYSBhY2NlcHRfYnl0ZXMsIGFuZCB0aGVuCi0gICAgdGhlIHJlc3BvbnNlIGJ5dGVzIHRvIGJl
IHJlYWQgdmlhIHJlYWRfYnl0ZXMuCi0KLSAgICBGb3IgaW5zdGFuY2U6Ci0gICAgcmVxdWVzdC5h
Y2NlcHRfYnl0ZXMoJzEyMycpCi0gICAgcmVxdWVzdC5maW5pc2hlZF93cml0aW5nKCkKLSAgICBy
ZXN1bHQgPSByZXF1ZXN0LnJlYWRfYnl0ZXMoMykKLSAgICByZXF1ZXN0LmZpbmlzaGVkX3JlYWRp
bmcoKQotCi0gICAgSXQgaXMgdXAgdG8gdGhlIGluZGl2aWR1YWwgU21hcnRDbGllbnRNZWRpdW0g
d2hldGhlciBtdWx0aXBsZSBjb25jdXJyZW50Ci0gICAgcmVxdWVzdHMgY2FuIGV4aXN0LiBTZWUg
U21hcnRDbGllbnRNZWRpdW0uZ2V0X3JlcXVlc3QgdG8gb2J0YWluIGluc3RhbmNlcyAKLSAgICBv
ZiBTbWFydENsaWVudE1lZGl1bVJlcXVlc3QsIGFuZCB0aGUgY29uY3JldGUgTWVkaXVtIHlvdSBh
cmUgdXNpbmcgZm9yIAotICAgIGRldGFpbHMgb24gY29uY3VycmVuY3kgYW5kIHBpcGVsaW5pbmcu
Ci0gICAgIiIiCi0KLSAgICBkZWYgX19pbml0X18oc2VsZiwgbWVkaXVtKToKLSAgICAgICAgIiIi
Q29uc3RydWN0IGEgU21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0IGZvciB0aGUgbWVkaXVtIG1lZGl1
bS4iIiIKLSAgICAgICAgc2VsZi5fbWVkaXVtID0gbWVkaXVtCi0gICAgICAgICMgd2UgdHJhY2sg
c3RhdGUgYnkgY29uc3RhbnRzIC0gd2UgbWF5IHdhbnQgdG8gdXNlIHRoZSBzYW1lCi0gICAgICAg
ICMgcGF0dGVybiBhcyBCb2R5UmVhZGVyIGlmIGl0IGdldHMgbW9yZSBjb21wbGV4LgotICAgICAg
ICAjIHZhbGlkIHN0YXRlcyBhcmU6ICJ3cml0aW5nIiwgInJlYWRpbmciLCAiZG9uZSIKLSAgICAg
ICAgc2VsZi5fc3RhdGUgPSAid3JpdGluZyIKLQotICAgIGRlZiBhY2NlcHRfYnl0ZXMoc2VsZiwg
Ynl0ZXMpOgotICAgICAgICAiIiJBY2NlcHQgYnl0ZXMgZm9yIGluY2x1c2lvbiBpbiB0aGlzIHJl
cXVlc3QuCi0KLSAgICAgICAgVGhpcyBtZXRob2QgbWF5IG5vdCBiZSBiZSBjYWxsZWQgYWZ0ZXIg
ZmluaXNoZWRfd3JpdGluZygpIGhhcyBiZWVuCi0gICAgICAgIGNhbGxlZC4gIEl0IGRlcGVuZHMg
dXBvbiB0aGUgTWVkaXVtIHdoZXRoZXIgb3Igbm90IHRoZSBieXRlcyB3aWxsIGJlCi0gICAgICAg
IGltbWVkaWF0ZWx5IHRyYW5zbWl0dGVkLiBNZXNzYWdlIGJhc2VkIE1lZGl1bXMgd2lsbCB0ZW5k
IHRvIGJ1ZmZlciB0aGUKLSAgICAgICAgYnl0ZXMgdW50aWwgZmluaXNoZWRfd3JpdGluZygpIGlz
IGNhbGxlZC4KLQotICAgICAgICA6cGFyYW0gYnl0ZXM6IEEgYnl0ZXN0cmluZy4KLSAgICAgICAg
IiIiCi0gICAgICAgIGlmIHNlbGYuX3N0YXRlICE9ICJ3cml0aW5nIjoKLSAgICAgICAgICAgIHJh
aXNlIGVycm9ycy5Xcml0aW5nQ29tcGxldGVkKHNlbGYpCi0gICAgICAgIHNlbGYuX2FjY2VwdF9i
eXRlcyhieXRlcykKLQotICAgIGRlZiBfYWNjZXB0X2J5dGVzKHNlbGYsIGJ5dGVzKToKLSAgICAg
ICAgIiIiSGVscGVyIGZvciBhY2NlcHRfYnl0ZXMuCi0KLSAgICAgICAgQWNjZXB0X2J5dGVzIGNo
ZWNrcyB0aGUgc3RhdGUgb2YgdGhlIHJlcXVlc3QgdG8gZGV0ZXJtaW5nIGlmIGJ5dGVzCi0gICAg
ICAgIHNob3VsZCBiZSBhY2NlcHRlZC4gQWZ0ZXIgdGhhdCBpdCBoYW5kcyBvZmYgdG8gX2FjY2Vw
dF9ieXRlcyB0byBkbyB0aGUKLSAgICAgICAgYWN0dWFsIGFjY2VwdGFuY2UuCi0gICAgICAgICIi
IgotICAgICAgICByYWlzZSBOb3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuX2FjY2VwdF9ieXRlcykK
LQotICAgIGRlZiBmaW5pc2hlZF9yZWFkaW5nKHNlbGYpOgotICAgICAgICAiIiJJbmZvcm0gdGhl
IHJlcXVlc3QgdGhhdCBhbGwgZGVzaXJlZCBkYXRhIGhhcyBiZWVuIHJlYWQuCi0KLSAgICAgICAg
VGhpcyB3aWxsIHJlbW92ZSB0aGUgcmVxdWVzdCBmcm9tIHRoZSBwaXBlbGluZSBmb3IgaXRzIG1l
ZGl1bSAoaWYgdGhlCi0gICAgICAgIG1lZGl1bSBzdXBwb3J0cyBwaXBlbGluaW5nKSBhbmQgYW55
IGZ1cnRoZXIgY2FsbHMgdG8gbWV0aG9kcyBvbiB0aGUKLSAgICAgICAgcmVxdWVzdCB3aWxsIHJh
aXNlIFJlYWRpbmdDb21wbGV0ZWQuCi0gICAgICAgICIiIgotICAgICAgICBpZiBzZWxmLl9zdGF0
ZSA9PSAid3JpdGluZyI6Ci0gICAgICAgICAgICByYWlzZSBlcnJvcnMuV3JpdGluZ05vdENvbXBs
ZXRlKHNlbGYpCi0gICAgICAgIGlmIHNlbGYuX3N0YXRlICE9ICJyZWFkaW5nIjoKLSAgICAgICAg
ICAgIHJhaXNlIGVycm9ycy5SZWFkaW5nQ29tcGxldGVkKHNlbGYpCi0gICAgICAgIHNlbGYuX3N0
YXRlID0gImRvbmUiCi0gICAgICAgIHNlbGYuX2ZpbmlzaGVkX3JlYWRpbmcoKQotCi0gICAgZGVm
IF9maW5pc2hlZF9yZWFkaW5nKHNlbGYpOgotICAgICAgICAiIiJIZWxwZXIgZm9yIGZpbmlzaGVk
X3JlYWRpbmcuCi0KLSAgICAgICAgZmluaXNoZWRfcmVhZGluZyBjaGVja3MgdGhlIHN0YXRlIG9m
IHRoZSByZXF1ZXN0IHRvIGRldGVybWluZSBpZiAKLSAgICAgICAgZmluaXNoZWRfcmVhZGluZyBp
cyBhbGxvd2VkLCBhbmQgaWYgaXQgaXMgaGFuZHMgb2ZmIHRvIF9maW5pc2hlZF9yZWFkaW5nCi0g
ICAgICAgIHRvIHBlcmZvcm0gdGhlIGFjdGlvbi4KLSAgICAgICAgIiIiCi0gICAgICAgIHJhaXNl
IE5vdEltcGxlbWVudGVkRXJyb3Ioc2VsZi5fZmluaXNoZWRfcmVhZGluZykKLQotICAgIGRlZiBm
aW5pc2hlZF93cml0aW5nKHNlbGYpOgotICAgICAgICAiIiJGaW5pc2ggdGhlIHdyaXRpbmcgcGhh
c2Ugb2YgdGhpcyByZXF1ZXN0LgotCi0gICAgICAgIFRoaXMgd2lsbCBmbHVzaCBhbGwgcGVuZGlu
ZyBkYXRhIGZvciB0aGlzIHJlcXVlc3QgYWxvbmcgdGhlIG1lZGl1bS4KLSAgICAgICAgQWZ0ZXIg
Y2FsbGluZyBmaW5pc2hlZF93cml0aW5nLCB5b3UgbWF5IG5vdCBjYWxsIGFjY2VwdF9ieXRlcyBh
bnltb3JlLgotICAgICAgICAiIiIKLSAgICAgICAgaWYgc2VsZi5fc3RhdGUgIT0gIndyaXRpbmci
OgotICAgICAgICAgICAgcmFpc2UgZXJyb3JzLldyaXRpbmdDb21wbGV0ZWQoc2VsZikKLSAgICAg
ICAgc2VsZi5fc3RhdGUgPSAicmVhZGluZyIKLSAgICAgICAgc2VsZi5fZmluaXNoZWRfd3JpdGlu
ZygpCi0KLSAgICBkZWYgX2ZpbmlzaGVkX3dyaXRpbmcoc2VsZik6Ci0gICAgICAgICIiIkhlbHBl
ciBmb3IgZmluaXNoZWRfd3JpdGluZy4KLQotICAgICAgICBmaW5pc2hlZF93cml0aW5nIGNoZWNr
cyB0aGUgc3RhdGUgb2YgdGhlIHJlcXVlc3QgdG8gZGV0ZXJtaW5lIGlmIAotICAgICAgICBmaW5p
c2hlZF93cml0aW5nIGlzIGFsbG93ZWQsIGFuZCBpZiBpdCBpcyBoYW5kcyBvZmYgdG8gX2Zpbmlz
aGVkX3dyaXRpbmcKLSAgICAgICAgdG8gcGVyZm9ybSB0aGUgYWN0aW9uLgotICAgICAgICAiIiIK
LSAgICAgICAgcmFpc2UgTm90SW1wbGVtZW50ZWRFcnJvcihzZWxmLl9maW5pc2hlZF93cml0aW5n
KQotCi0gICAgZGVmIHJlYWRfYnl0ZXMoc2VsZiwgY291bnQpOgotICAgICAgICAiIiJSZWFkIGJ5
dGVzIGZyb20gdGhpcyByZXF1ZXN0cyByZXNwb25zZS4KLQotICAgICAgICBUaGlzIG1ldGhvZCB3
aWxsIGJsb2NrIGFuZCB3YWl0IGZvciBjb3VudCBieXRlcyB0byBiZSByZWFkLiBJdCBtYXkgbm90
Ci0gICAgICAgIGJlIGludm9rZWQgdW50aWwgZmluaXNoZWRfd3JpdGluZygpIGhhcyBiZWVuIGNh
bGxlZCAtIHRoaXMgaXMgdG8gZW5zdXJlCi0gICAgICAgIGEgbWVzc2FnZS1iYXNlZCBhcHByb2Fj
aCB0byByZXF1ZXN0cywgZm9yIGNvbXBhdGFiaWxpdHkgd2l0aCBtZXNzYWdlCi0gICAgICAgIGJh
c2VkIG1lZGl1bXMgbGlrZSBIVFRQLgotICAgICAgICAiIiIKLSAgICAgICAgaWYgc2VsZi5fc3Rh
dGUgPT0gIndyaXRpbmciOgotICAgICAgICAgICAgcmFpc2UgZXJyb3JzLldyaXRpbmdOb3RDb21w
bGV0ZShzZWxmKQotICAgICAgICBpZiBzZWxmLl9zdGF0ZSAhPSAicmVhZGluZyI6Ci0gICAgICAg
ICAgICByYWlzZSBlcnJvcnMuUmVhZGluZ0NvbXBsZXRlZChzZWxmKQotICAgICAgICByZXR1cm4g
c2VsZi5fcmVhZF9ieXRlcyhjb3VudCkKLQotICAgIGRlZiBfcmVhZF9ieXRlcyhzZWxmLCBjb3Vu
dCk6Ci0gICAgICAgICIiIkhlbHBlciBmb3IgcmVhZF9ieXRlcy4KLQotICAgICAgICByZWFkX2J5
dGVzIGNoZWNrcyB0aGUgc3RhdGUgb2YgdGhlIHJlcXVlc3QgdG8gZGV0ZXJtaW5nIGlmIGJ5dGVz
Ci0gICAgICAgIHNob3VsZCBiZSByZWFkLiBBZnRlciB0aGF0IGl0IGhhbmRzIG9mZiB0byBfcmVh
ZF9ieXRlcyB0byBkbyB0aGUKLSAgICAgICAgYWN0dWFsIHJlYWQuCi0gICAgICAgICIiIgotICAg
ICAgICByYWlzZSBOb3RJbXBsZW1lbnRlZEVycm9yKHNlbGYuX3JlYWRfYnl0ZXMpCi0KLQotY2xh
c3MgU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0KFNtYXJ0Q2xpZW50TWVkaXVtUmVxdWVz
dCk6Ci0gICAgIiIiQSBTbWFydENsaWVudE1lZGl1bVJlcXVlc3QgdGhhdCB3b3JrcyB3aXRoIGFu
IFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtLiIiIgotCi0gICAgZGVmIF9faW5pdF9fKHNlbGYsIG1l
ZGl1bSk6Ci0gICAgICAgIFNtYXJ0Q2xpZW50TWVkaXVtUmVxdWVzdC5fX2luaXRfXyhzZWxmLCBt
ZWRpdW0pCi0gICAgICAgICMgY2hlY2sgdGhhdCB3ZSBhcmUgc2FmZSBjb25jdXJyZW5jeSB3aXNl
LiBJZiBzb21lIHN0cmVhbXMgc3RhcnQKLSAgICAgICAgIyBhbGxvd2luZyBjb25jdXJyZW50IHJl
cXVlc3RzIC0gaS5lLiB2aWEgbXVsdGlwbGV4aW5nIC0gdGhlbiB0aGlzCi0gICAgICAgICMgYXNz
ZXJ0IHNob3VsZCBiZSBtb3ZlZCB0byBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5nZXRfcmVxdWVz
dCwKLSAgICAgICAgIyBhbmQgdGhlIHNldHRpbmcvdW5zZXR0aW5nIG9mIF9jdXJyZW50X3JlcXVl
c3QgbGlrZXdpc2UgbW92ZWQgaW50bwotICAgICAgICAjIHRoYXQgY2xhc3MgOiBidXQgaXRzIHVu
bmVlZGVkIG92ZXJoZWFkIGZvciBub3cuIFJCQyAyMDA2MDkyMgotICAgICAgICBpZiBzZWxmLl9t
ZWRpdW0uX2N1cnJlbnRfcmVxdWVzdCBpcyBub3QgTm9uZToKLSAgICAgICAgICAgIHJhaXNlIGVy
cm9ycy5Ub29NYW55Q29uY3VycmVudFJlcXVlc3RzKHNlbGYuX21lZGl1bSkKLSAgICAgICAgc2Vs
Zi5fbWVkaXVtLl9jdXJyZW50X3JlcXVlc3QgPSBzZWxmCi0KLSAgICBkZWYgX2FjY2VwdF9ieXRl
cyhzZWxmLCBieXRlcyk6Ci0gICAgICAgICIiIlNlZSBTbWFydENsaWVudE1lZGl1bVJlcXVlc3Qu
X2FjY2VwdF9ieXRlcy4KLSAgICAgICAgCi0gICAgICAgIFRoaXMgZm9yd2FyZHMgdG8gc2VsZi5f
bWVkaXVtLl9hY2NlcHRfYnl0ZXMgYmVjYXVzZSB3ZSBhcmUgb3BlcmF0aW5nCi0gICAgICAgIG9u
IHRoZSBtZWRpdW1zIHN0cmVhbS4KLSAgICAgICAgIiIiCi0gICAgICAgIHNlbGYuX21lZGl1bS5f
YWNjZXB0X2J5dGVzKGJ5dGVzKQotCi0gICAgZGVmIF9maW5pc2hlZF9yZWFkaW5nKHNlbGYpOgot
ICAgICAgICAiIiJTZWUgU21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0Ll9maW5pc2hlZF9yZWFkaW5n
LgotCi0gICAgICAgIFRoaXMgY2xlYXJzIHRoZSBfY3VycmVudF9yZXF1ZXN0IG9uIHNlbGYuX21l
ZGl1bSB0byBhbGxvdyBhIG5ldyAKLSAgICAgICAgcmVxdWVzdCB0byBiZSBjcmVhdGVkLgotICAg
ICAgICAiIiIKLSAgICAgICAgYXNzZXJ0IHNlbGYuX21lZGl1bS5fY3VycmVudF9yZXF1ZXN0IGlz
IHNlbGYKLSAgICAgICAgc2VsZi5fbWVkaXVtLl9jdXJyZW50X3JlcXVlc3QgPSBOb25lCi0gICAg
ICAgIAotICAgIGRlZiBfZmluaXNoZWRfd3JpdGluZyhzZWxmKToKLSAgICAgICAgIiIiU2VlIFNt
YXJ0Q2xpZW50TWVkaXVtUmVxdWVzdC5fZmluaXNoZWRfd3JpdGluZy4KLQotICAgICAgICBUaGlz
IGludm9rZXMgc2VsZi5fbWVkaXVtLl9mbHVzaCB0byBlbnN1cmUgYWxsIGJ5dGVzIGFyZSB0cmFu
c21pdHRlZC4KLSAgICAgICAgIiIiCi0gICAgICAgIHNlbGYuX21lZGl1bS5fZmx1c2goKQotCi0g
ICAgZGVmIF9yZWFkX2J5dGVzKHNlbGYsIGNvdW50KToKLSAgICAgICAgIiIiU2VlIFNtYXJ0Q2xp
ZW50TWVkaXVtUmVxdWVzdC5fcmVhZF9ieXRlcy4KLSAgICAgICAgCi0gICAgICAgIFRoaXMgZm9y
d2FyZHMgdG8gc2VsZi5fbWVkaXVtLl9yZWFkX2J5dGVzIGJlY2F1c2Ugd2UgYXJlIG9wZXJhdGlu
ZwotICAgICAgICBvbiB0aGUgbWVkaXVtcyBzdHJlYW0uCi0gICAgICAgICIiIgotICAgICAgICBy
ZXR1cm4gc2VsZi5fbWVkaXVtLl9yZWFkX2J5dGVzKGNvdW50KQotCi0KLWNsYXNzIFNtYXJ0Q2xp
ZW50UmVxdWVzdFByb3RvY29sT25lKFNtYXJ0UHJvdG9jb2xCYXNlKToKLSAgICAiIiJUaGUgY2xp
ZW50LXNpZGUgcHJvdG9jb2wgZm9yIHNtYXJ0IHZlcnNpb24gMS4iIiIKLQotICAgIGRlZiBfX2lu
aXRfXyhzZWxmLCByZXF1ZXN0KToKLSAgICAgICAgIiIiQ29uc3RydWN0IGEgU21hcnRDbGllbnRS
ZXF1ZXN0UHJvdG9jb2xPbmUuCi0KLSAgICAgICAgOnBhcmFtIHJlcXVlc3Q6IEEgU21hcnRDbGll
bnRNZWRpdW1SZXF1ZXN0IHRvIHNlcmlhbGlzZSBvbnRvIGFuZAotICAgICAgICAgICAgZGVzZXJp
YWxpc2UgZnJvbS4KLSAgICAgICAgIiIiCi0gICAgICAgIHNlbGYuX3JlcXVlc3QgPSByZXF1ZXN0
Ci0gICAgICAgIHNlbGYuX2JvZHlfYnVmZmVyID0gTm9uZQotCi0gICAgZGVmIGNhbGwoc2VsZiwg
KmFyZ3MpOgotICAgICAgICBieXRlcyA9IF9lbmNvZGVfdHVwbGUoYXJncykKLSAgICAgICAgc2Vs
Zi5fcmVxdWVzdC5hY2NlcHRfYnl0ZXMoYnl0ZXMpCi0gICAgICAgIHNlbGYuX3JlcXVlc3QuZmlu
aXNoZWRfd3JpdGluZygpCi0KLSAgICBkZWYgY2FsbF93aXRoX2JvZHlfYnl0ZXMoc2VsZiwgYXJn
cywgYm9keSk6Ci0gICAgICAgICIiIk1ha2UgYSByZW1vdGUgY2FsbCBvZiBhcmdzIHdpdGggYm9k
eSBieXRlcyAnYm9keScuCi0KLSAgICAgICAgQWZ0ZXIgY2FsbGluZyB0aGlzLCBjYWxsIHJlYWRf
cmVzcG9uc2VfdHVwbGUgdG8gZmluZCB0aGUgcmVzdWx0IG91dC4KLSAgICAgICAgIiIiCi0gICAg
ICAgIGJ5dGVzID0gX2VuY29kZV90dXBsZShhcmdzKQotICAgICAgICBzZWxmLl9yZXF1ZXN0LmFj
Y2VwdF9ieXRlcyhieXRlcykKLSAgICAgICAgYnl0ZXMgPSBzZWxmLl9lbmNvZGVfYnVsa19kYXRh
KGJvZHkpCi0gICAgICAgIHNlbGYuX3JlcXVlc3QuYWNjZXB0X2J5dGVzKGJ5dGVzKQotICAgICAg
ICBzZWxmLl9yZXF1ZXN0LmZpbmlzaGVkX3dyaXRpbmcoKQotCi0gICAgZGVmIGNhbGxfd2l0aF9i
b2R5X3JlYWR2X2FycmF5KHNlbGYsIGFyZ3MsIGJvZHkpOgotICAgICAgICAiIiJNYWtlIGEgcmVt
b3RlIGNhbGwgd2l0aCBhIHJlYWR2IGFycmF5LgotCi0gICAgICAgIFRoZSBib2R5IGlzIGVuY29k
ZWQgd2l0aCBvbmUgbGluZSBwZXIgcmVhZHYgb2Zmc2V0IHBhaXIuIFRoZSBudW1iZXJzIGluCi0g
ICAgICAgIGVhY2ggcGFpciBhcmUgc2VwYXJhdGVkIGJ5IGEgY29tbWEsIGFuZCBubyB0cmFpbGlu
ZyBcbiBpcyBlbWl0dGVkLgotICAgICAgICAiIiIKLSAgICAgICAgYnl0ZXMgPSBfZW5jb2RlX3R1
cGxlKGFyZ3MpCi0gICAgICAgIHNlbGYuX3JlcXVlc3QuYWNjZXB0X2J5dGVzKGJ5dGVzKQotICAg
ICAgICByZWFkdl9ieXRlcyA9IHNlbGYuX3NlcmlhbGlzZV9vZmZzZXRzKGJvZHkpCi0gICAgICAg
IGJ5dGVzID0gc2VsZi5fZW5jb2RlX2J1bGtfZGF0YShyZWFkdl9ieXRlcykKLSAgICAgICAgc2Vs
Zi5fcmVxdWVzdC5hY2NlcHRfYnl0ZXMoYnl0ZXMpCi0gICAgICAgIHNlbGYuX3JlcXVlc3QuZmlu
aXNoZWRfd3JpdGluZygpCi0KLSAgICBkZWYgY2FuY2VsX3JlYWRfYm9keShzZWxmKToKLSAgICAg
ICAgIiIiQWZ0ZXIgZXhwZWN0aW5nIGEgYm9keSwgYSByZXNwb25zZSBjb2RlIG1heSBpbmRpY2F0
ZSBvbmUgb3RoZXJ3aXNlLgotCi0gICAgICAgIFRoaXMgbWV0aG9kIGxldHMgdGhlIGRvbWFpbiBj
bGllbnQgaW5mb3JtIHRoZSBwcm90b2NvbCB0aGF0IG5vIGJvZHkKLSAgICAgICAgd2lsbCBiZSB0
cmFuc21pdHRlZC4gVGhpcyBpcyBhIHRlcm1pbmFsIG1ldGhvZDogYWZ0ZXIgY2FsbGluZyBpdCB0
aGUKLSAgICAgICAgcHJvdG9jb2wgaXMgbm90IGFibGUgdG8gYmUgdXNlZCBmdXJ0aGVyLgotICAg
ICAgICAiIiIKLSAgICAgICAgc2VsZi5fcmVxdWVzdC5maW5pc2hlZF9yZWFkaW5nKCkKLQotICAg
IGRlZiByZWFkX3Jlc3BvbnNlX3R1cGxlKHNlbGYsIGV4cGVjdF9ib2R5PUZhbHNlKToKLSAgICAg
ICAgIiIiUmVhZCBhIHJlc3BvbnNlIHR1cGxlIGZyb20gdGhlIHdpcmUuCi0KLSAgICAgICAgVGhp
cyBzaG91bGQgb25seSBiZSBjYWxsZWQgb25jZS4KLSAgICAgICAgIiIiCi0gICAgICAgIHJlc3Vs
dCA9IHNlbGYuX3JlY3ZfdHVwbGUoKQotICAgICAgICBpZiBub3QgZXhwZWN0X2JvZHk6Ci0gICAg
ICAgICAgICBzZWxmLl9yZXF1ZXN0LmZpbmlzaGVkX3JlYWRpbmcoKQotICAgICAgICByZXR1cm4g
cmVzdWx0Ci0KLSAgICBkZWYgcmVhZF9ib2R5X2J5dGVzKHNlbGYsIGNvdW50PS0xKToKLSAgICAg
ICAgIiIiUmVhZCBieXRlcyBmcm9tIHRoZSBib2R5LCBkZWNvZGluZyBpbnRvIGEgYnl0ZSBzdHJl
YW0uCi0gICAgICAgIAotICAgICAgICBXZSByZWFkIGFsbCBieXRlcyBhdCBvbmNlIHRvIGVuc3Vy
ZSB3ZSd2ZSBjaGVja2VkIHRoZSB0cmFpbGVyIGZvciAKLSAgICAgICAgZXJyb3JzLCBhbmQgdGhl
biBmZWVkIHRoZSBidWZmZXIgYmFjayBhcyByZWFkX2JvZHlfYnl0ZXMgaXMgY2FsbGVkLgotICAg
ICAgICAiIiIKLSAgICAgICAgaWYgc2VsZi5fYm9keV9idWZmZXIgaXMgbm90IE5vbmU6Ci0gICAg
ICAgICAgICByZXR1cm4gc2VsZi5fYm9keV9idWZmZXIucmVhZChjb3VudCkKLSAgICAgICAgX2Jv
ZHlfZGVjb2RlciA9IExlbmd0aFByZWZpeGVkQm9keURlY29kZXIoKQotCi0gICAgICAgIHdoaWxl
IG5vdCBfYm9keV9kZWNvZGVyLmZpbmlzaGVkX3JlYWRpbmc6Ci0gICAgICAgICAgICBieXRlc193
YW50ZWQgPSBfYm9keV9kZWNvZGVyLm5leHRfcmVhZF9zaXplKCkKLSAgICAgICAgICAgIGJ5dGVz
ID0gc2VsZi5fcmVxdWVzdC5yZWFkX2J5dGVzKGJ5dGVzX3dhbnRlZCkKLSAgICAgICAgICAgIF9i
b2R5X2RlY29kZXIuYWNjZXB0X2J5dGVzKGJ5dGVzKQotICAgICAgICBzZWxmLl9yZXF1ZXN0LmZp
bmlzaGVkX3JlYWRpbmcoKQotICAgICAgICBzZWxmLl9ib2R5X2J1ZmZlciA9IFN0cmluZ0lPKF9i
b2R5X2RlY29kZXIucmVhZF9wZW5kaW5nX2RhdGEoKSkKLSAgICAgICAgIyBYWFg6IFRPRE8gY2hl
Y2sgdGhlIHRyYWlsZXIgcmVzdWx0LgotICAgICAgICByZXR1cm4gc2VsZi5fYm9keV9idWZmZXIu
cmVhZChjb3VudCkKLQotICAgIGRlZiBfcmVjdl90dXBsZShzZWxmKToKLSAgICAgICAgIiIiUmVj
ZWl2ZSBhIHR1cGxlIGZyb20gdGhlIG1lZGl1bSByZXF1ZXN0LiIiIgotICAgICAgICBsaW5lID0g
JycKLSAgICAgICAgd2hpbGUgbm90IGxpbmUgb3IgbGluZVstMV0gIT0gJ1xuJzoKLSAgICAgICAg
ICAgICMgVE9ETzogdGhpcyBpcyBpbmVmZmljaWVudCAtIGJ1dCB0dXBsZXMgYXJlIHNob3J0Lgot
ICAgICAgICAgICAgbmV3X2NoYXIgPSBzZWxmLl9yZXF1ZXN0LnJlYWRfYnl0ZXMoMSkKLSAgICAg
ICAgICAgIGxpbmUgKz0gbmV3X2NoYXIKLSAgICAgICAgICAgIGFzc2VydCBuZXdfY2hhciAhPSAn
JywgImVuZCBvZiBmaWxlIHJlYWRpbmcgZnJvbSBzZXJ2ZXIuIgotICAgICAgICByZXR1cm4gX2Rl
Y29kZV90dXBsZShsaW5lKQotCi0gICAgZGVmIHF1ZXJ5X3ZlcnNpb24oc2VsZik6Ci0gICAgICAg
ICIiIlJldHVybiBwcm90b2NvbCB2ZXJzaW9uIG51bWJlciBvZiB0aGUgc2VydmVyLiIiIgotICAg
ICAgICBzZWxmLmNhbGwoJ2hlbGxvJykKLSAgICAgICAgcmVzcCA9IHNlbGYucmVhZF9yZXNwb25z
ZV90dXBsZSgpCi0gICAgICAgIGlmIHJlc3AgPT0gKCdvaycsICcxJyk6Ci0gICAgICAgICAgICBy
ZXR1cm4gMQotICAgICAgICBlbHNlOgotICAgICAgICAgICAgcmFpc2UgZXJyb3JzLlNtYXJ0UHJv
dG9jb2xFcnJvcigiYmFkIHJlc3BvbnNlICVyIiAlIChyZXNwLCkpCi0KLQotY2xhc3MgU21hcnRD
bGllbnRNZWRpdW0ob2JqZWN0KToKLSAgICAiIiJTbWFydCBjbGllbnQgaXMgYSBtZWRpdW0gZm9y
IHNlbmRpbmcgc21hcnQgcHJvdG9jb2wgcmVxdWVzdHMgb3Zlci4iIiIKLQotICAgIGRlZiBkaXNj
b25uZWN0KHNlbGYpOgotICAgICAgICAiIiJJZiB0aGlzIG1lZGl1bSBtYWludGFpbnMgYSBwZXJz
aXN0ZW50IGNvbm5lY3Rpb24sIGNsb3NlIGl0LgotICAgICAgICAKLSAgICAgICAgVGhlIGRlZmF1
bHQgaW1wbGVtZW50YXRpb24gZG9lcyBub3RoaW5nLgotICAgICAgICAiIiIKLSAgICAgICAgCi0K
LWNsYXNzIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtKFNtYXJ0Q2xpZW50TWVkaXVtKToKLSAgICAi
IiJTdHJlYW0gYmFzZWQgbWVkaXVtIGNvbW1vbiBjbGFzcy4KLQotICAgIFNtYXJ0Q2xpZW50U3Ry
ZWFtTWVkaXVtcyBvcGVyYXRlIG9uIGEgc3RyZWFtLiBBbGwgc3ViY2xhc3NlcyB1c2UgYSBjb21t
b24KLSAgICBTbWFydENsaWVudFN0cmVhbU1lZGl1bVJlcXVlc3QgZm9yIHRoZWlyIHJlcXVlc3Rz
LCBhbmQgc2hvdWxkIGltcGxlbWVudAotICAgIF9hY2NlcHRfYnl0ZXMgYW5kIF9yZWFkX2J5dGVz
IHRvIGFsbG93IHRoZSByZXF1ZXN0IG9iamVjdHMgdG8gc2VuZCBhbmQKLSAgICByZWNlaXZlIGJ5
dGVzLgotICAgICIiIgotCi0gICAgZGVmIF9faW5pdF9fKHNlbGYpOgotICAgICAgICBzZWxmLl9j
dXJyZW50X3JlcXVlc3QgPSBOb25lCi0KLSAgICBkZWYgYWNjZXB0X2J5dGVzKHNlbGYsIGJ5dGVz
KToKLSAgICAgICAgc2VsZi5fYWNjZXB0X2J5dGVzKGJ5dGVzKQotCi0gICAgZGVmIF9fZGVsX18o
c2VsZik6Ci0gICAgICAgICIiIlRoZSBTbWFydENsaWVudFN0cmVhbU1lZGl1bSBrbm93cyBob3cg
dG8gY2xvc2UgdGhlIHN0cmVhbSB3aGVuIGl0IGlzCi0gICAgICAgIGZpbmlzaGVkIHdpdGggaXQu
Ci0gICAgICAgICIiIgotICAgICAgICBzZWxmLmRpc2Nvbm5lY3QoKQotCi0gICAgZGVmIF9mbHVz
aChzZWxmKToKLSAgICAgICAgIiIiRmx1c2ggdGhlIG91dHB1dCBzdHJlYW0uCi0gICAgICAgIAot
ICAgICAgICBUaGlzIG1ldGhvZCBpcyB1c2VkIGJ5IHRoZSBTbWFydENsaWVudFN0cmVhbU1lZGl1
bVJlcXVlc3QgdG8gZW5zdXJlIHRoYXQKLSAgICAgICAgYWxsIGRhdGEgZm9yIGEgcmVxdWVzdCBp
cyBzZW50LCB0byBhdm9pZCBsb25nIHRpbWVvdXRzIG9yIGRlYWRsb2Nrcy4KLSAgICAgICAgIiIi
Ci0gICAgICAgIHJhaXNlIE5vdEltcGxlbWVudGVkRXJyb3Ioc2VsZi5fZmx1c2gpCi0KLSAgICBk
ZWYgZ2V0X3JlcXVlc3Qoc2VsZik6Ci0gICAgICAgICIiIlNlZSBTbWFydENsaWVudE1lZGl1bS5n
ZXRfcmVxdWVzdCgpLgotCi0gICAgICAgIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtIGFsd2F5cyBy
ZXR1cm5zIGEgU21hcnRDbGllbnRTdHJlYW1NZWRpdW1SZXF1ZXN0Ci0gICAgICAgIGZvciBnZXRf
cmVxdWVzdC4KLSAgICAgICAgIiIiCi0gICAgICAgIHJldHVybiBTbWFydENsaWVudFN0cmVhbU1l
ZGl1bVJlcXVlc3Qoc2VsZikKLQotICAgIGRlZiByZWFkX2J5dGVzKHNlbGYsIGNvdW50KToKLSAg
ICAgICAgcmV0dXJuIHNlbGYuX3JlYWRfYnl0ZXMoY291bnQpCi0KLQotY2xhc3MgU21hcnRTaW1w
bGVQaXBlc0NsaWVudE1lZGl1bShTbWFydENsaWVudFN0cmVhbU1lZGl1bSk6Ci0gICAgIiIiQSBj
bGllbnQgbWVkaXVtIHVzaW5nIHNpbXBsZSBwaXBlcy4KLSAgICAKLSAgICBUaGlzIGNsaWVudCBk
b2VzIG5vdCBtYW5hZ2UgdGhlIHBpcGVzOiBpdCBhc3N1bWVzIHRoZXkgd2lsbCBhbHdheXMgYmUg
b3Blbi4KLSAgICAiIiIKLQotICAgIGRlZiBfX2luaXRfXyhzZWxmLCByZWFkYWJsZV9waXBlLCB3
cml0ZWFibGVfcGlwZSk6Ci0gICAgICAgIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtLl9faW5pdF9f
KHNlbGYpCi0gICAgICAgIHNlbGYuX3JlYWRhYmxlX3BpcGUgPSByZWFkYWJsZV9waXBlCi0gICAg
ICAgIHNlbGYuX3dyaXRlYWJsZV9waXBlID0gd3JpdGVhYmxlX3BpcGUKLQotICAgIGRlZiBfYWNj
ZXB0X2J5dGVzKHNlbGYsIGJ5dGVzKToKLSAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50U3RyZWFt
TWVkaXVtLmFjY2VwdF9ieXRlcy4iIiIKLSAgICAgICAgc2VsZi5fd3JpdGVhYmxlX3BpcGUud3Jp
dGUoYnl0ZXMpCi0KLSAgICBkZWYgX2ZsdXNoKHNlbGYpOgotICAgICAgICAiIiJTZWUgU21hcnRD
bGllbnRTdHJlYW1NZWRpdW0uX2ZsdXNoKCkuIiIiCi0gICAgICAgIHNlbGYuX3dyaXRlYWJsZV9w
aXBlLmZsdXNoKCkKLQotICAgIGRlZiBfcmVhZF9ieXRlcyhzZWxmLCBjb3VudCk6Ci0gICAgICAg
ICIiIlNlZSBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5fcmVhZF9ieXRlcy4iIiIKLSAgICAgICAg
cmV0dXJuIHNlbGYuX3JlYWRhYmxlX3BpcGUucmVhZChjb3VudCkKLQotCi1jbGFzcyBTbWFydFNT
SENsaWVudE1lZGl1bShTbWFydENsaWVudFN0cmVhbU1lZGl1bSk6Ci0gICAgIiIiQSBjbGllbnQg
bWVkaXVtIHVzaW5nIFNTSC4iIiIKLSAgICAKLSAgICBkZWYgX19pbml0X18oc2VsZiwgaG9zdCwg
cG9ydD1Ob25lLCB1c2VybmFtZT1Ob25lLCBwYXNzd29yZD1Ob25lLAotICAgICAgICAgICAgdmVu
ZG9yPU5vbmUpOgotICAgICAgICAiIiJDcmVhdGVzIGEgY2xpZW50IHRoYXQgd2lsbCBjb25uZWN0
IG9uIHRoZSBmaXJzdCB1c2UuCi0gICAgICAgIAotICAgICAgICA6cGFyYW0gdmVuZG9yOiBBbiBv
cHRpb25hbCBvdmVycmlkZSBmb3IgdGhlIHNzaCB2ZW5kb3IgdG8gdXNlLiBTZWUKLSAgICAgICAg
ICAgIGJ6cmxpYi50cmFuc3BvcnQuc3NoIGZvciBkZXRhaWxzIG9uIHNzaCB2ZW5kb3JzLgotICAg
ICAgICAiIiIKLSAgICAgICAgU21hcnRDbGllbnRTdHJlYW1NZWRpdW0uX19pbml0X18oc2VsZikK
LSAgICAgICAgc2VsZi5fY29ubmVjdGVkID0gRmFsc2UKLSAgICAgICAgc2VsZi5faG9zdCA9IGhv
c3QKLSAgICAgICAgc2VsZi5fcGFzc3dvcmQgPSBwYXNzd29yZAotICAgICAgICBzZWxmLl9wb3J0
ID0gcG9ydAotICAgICAgICBzZWxmLl91c2VybmFtZSA9IHVzZXJuYW1lCi0gICAgICAgIHNlbGYu
X3JlYWRfZnJvbSA9IE5vbmUKLSAgICAgICAgc2VsZi5fc3NoX2Nvbm5lY3Rpb24gPSBOb25lCi0g
ICAgICAgIHNlbGYuX3ZlbmRvciA9IHZlbmRvcgotICAgICAgICBzZWxmLl93cml0ZV90byA9IE5v
bmUKLQotICAgIGRlZiBfYWNjZXB0X2J5dGVzKHNlbGYsIGJ5dGVzKToKLSAgICAgICAgIiIiU2Vl
IFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtLmFjY2VwdF9ieXRlcy4iIiIKLSAgICAgICAgc2VsZi5f
ZW5zdXJlX2Nvbm5lY3Rpb24oKQotICAgICAgICBzZWxmLl93cml0ZV90by53cml0ZShieXRlcykK
LQotICAgIGRlZiBkaXNjb25uZWN0KHNlbGYpOgotICAgICAgICAiIiJTZWUgU21hcnRDbGllbnRN
ZWRpdW0uZGlzY29ubmVjdCgpLiIiIgotICAgICAgICBpZiBub3Qgc2VsZi5fY29ubmVjdGVkOgot
ICAgICAgICAgICAgcmV0dXJuCi0gICAgICAgIHNlbGYuX3JlYWRfZnJvbS5jbG9zZSgpCi0gICAg
ICAgIHNlbGYuX3dyaXRlX3RvLmNsb3NlKCkKLSAgICAgICAgc2VsZi5fc3NoX2Nvbm5lY3Rpb24u
Y2xvc2UoKQotICAgICAgICBzZWxmLl9jb25uZWN0ZWQgPSBGYWxzZQotCi0gICAgZGVmIF9lbnN1
cmVfY29ubmVjdGlvbihzZWxmKToKLSAgICAgICAgIiIiQ29ubmVjdCB0aGlzIG1lZGl1bSBpZiBu
b3QgYWxyZWFkeSBjb25uZWN0ZWQuIiIiCi0gICAgICAgIGlmIHNlbGYuX2Nvbm5lY3RlZDoKLSAg
ICAgICAgICAgIHJldHVybgotICAgICAgICBleGVjdXRhYmxlID0gb3MuZW52aXJvbi5nZXQoJ0Ja
Ul9SRU1PVEVfUEFUSCcsICdienInKQotICAgICAgICBpZiBzZWxmLl92ZW5kb3IgaXMgTm9uZToK
LSAgICAgICAgICAgIHZlbmRvciA9IHNzaC5fZ2V0X3NzaF92ZW5kb3IoKQotICAgICAgICBlbHNl
OgotICAgICAgICAgICAgdmVuZG9yID0gc2VsZi5fdmVuZG9yCi0gICAgICAgIHNlbGYuX3NzaF9j
b25uZWN0aW9uID0gdmVuZG9yLmNvbm5lY3Rfc3NoKHNlbGYuX3VzZXJuYW1lLAotICAgICAgICAg
ICAgICAgIHNlbGYuX3Bhc3N3b3JkLCBzZWxmLl9ob3N0LCBzZWxmLl9wb3J0LAotICAgICAgICAg
ICAgICAgIGNvbW1hbmQ9W2V4ZWN1dGFibGUsICdzZXJ2ZScsICctLWluZXQnLCAnLS1kaXJlY3Rv
cnk9LycsCi0gICAgICAgICAgICAgICAgICAgICAgICAgJy0tYWxsb3ctd3JpdGVzJ10pCi0gICAg
ICAgIHNlbGYuX3JlYWRfZnJvbSwgc2VsZi5fd3JpdGVfdG8gPSBcCi0gICAgICAgICAgICBzZWxm
Ll9zc2hfY29ubmVjdGlvbi5nZXRfZmlsZWxpa2VfY2hhbm5lbHMoKQotICAgICAgICBzZWxmLl9j
b25uZWN0ZWQgPSBUcnVlCi0KLSAgICBkZWYgX2ZsdXNoKHNlbGYpOgotICAgICAgICAiIiJTZWUg
U21hcnRDbGllbnRTdHJlYW1NZWRpdW0uX2ZsdXNoKCkuIiIiCi0gICAgICAgIHNlbGYuX3dyaXRl
X3RvLmZsdXNoKCkKLQotICAgIGRlZiBfcmVhZF9ieXRlcyhzZWxmLCBjb3VudCk6Ci0gICAgICAg
ICIiIlNlZSBTbWFydENsaWVudFN0cmVhbU1lZGl1bS5yZWFkX2J5dGVzLiIiIgotICAgICAgICBp
ZiBub3Qgc2VsZi5fY29ubmVjdGVkOgotICAgICAgICAgICAgcmFpc2UgZXJyb3JzLk1lZGl1bU5v
dENvbm5lY3RlZChzZWxmKQotICAgICAgICByZXR1cm4gc2VsZi5fcmVhZF9mcm9tLnJlYWQoY291
bnQpCi0KLQotY2xhc3MgU21hcnRUQ1BDbGllbnRNZWRpdW0oU21hcnRDbGllbnRTdHJlYW1NZWRp
dW0pOgotICAgICIiIkEgY2xpZW50IG1lZGl1bSB1c2luZyBUQ1AuIiIiCi0gICAgCi0gICAgZGVm
IF9faW5pdF9fKHNlbGYsIGhvc3QsIHBvcnQpOgotICAgICAgICAiIiJDcmVhdGVzIGEgY2xpZW50
IHRoYXQgd2lsbCBjb25uZWN0IG9uIHRoZSBmaXJzdCB1c2UuIiIiCi0gICAgICAgIFNtYXJ0Q2xp
ZW50U3RyZWFtTWVkaXVtLl9faW5pdF9fKHNlbGYpCi0gICAgICAgIHNlbGYuX2Nvbm5lY3RlZCA9
IEZhbHNlCi0gICAgICAgIHNlbGYuX2hvc3QgPSBob3N0Ci0gICAgICAgIHNlbGYuX3BvcnQgPSBw
b3J0Ci0gICAgICAgIHNlbGYuX3NvY2tldCA9IE5vbmUKLQotICAgIGRlZiBfYWNjZXB0X2J5dGVz
KHNlbGYsIGJ5dGVzKToKLSAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50TWVkaXVtLmFjY2VwdF9i
eXRlcy4iIiIKLSAgICAgICAgc2VsZi5fZW5zdXJlX2Nvbm5lY3Rpb24oKQotICAgICAgICBzZWxm
Ll9zb2NrZXQuc2VuZGFsbChieXRlcykKLQotICAgIGRlZiBkaXNjb25uZWN0KHNlbGYpOgotICAg
ICAgICAiIiJTZWUgU21hcnRDbGllbnRNZWRpdW0uZGlzY29ubmVjdCgpLiIiIgotICAgICAgICBp
ZiBub3Qgc2VsZi5fY29ubmVjdGVkOgotICAgICAgICAgICAgcmV0dXJuCi0gICAgICAgIHNlbGYu
X3NvY2tldC5jbG9zZSgpCi0gICAgICAgIHNlbGYuX3NvY2tldCA9IE5vbmUKLSAgICAgICAgc2Vs
Zi5fY29ubmVjdGVkID0gRmFsc2UKLQotICAgIGRlZiBfZW5zdXJlX2Nvbm5lY3Rpb24oc2VsZik6
Ci0gICAgICAgICIiIkNvbm5lY3QgdGhpcyBtZWRpdW0gaWYgbm90IGFscmVhZHkgY29ubmVjdGVk
LiIiIgotICAgICAgICBpZiBzZWxmLl9jb25uZWN0ZWQ6Ci0gICAgICAgICAgICByZXR1cm4KLSAg
ICAgICAgc2VsZi5fc29ja2V0ID0gc29ja2V0LnNvY2tldCgpCi0gICAgICAgIHNlbGYuX3NvY2tl
dC5zZXRzb2Nrb3B0KHNvY2tldC5JUFBST1RPX1RDUCwgc29ja2V0LlRDUF9OT0RFTEFZLCAxKQot
ICAgICAgICByZXN1bHQgPSBzZWxmLl9zb2NrZXQuY29ubmVjdF9leCgoc2VsZi5faG9zdCwgaW50
KHNlbGYuX3BvcnQpKSkKLSAgICAgICAgaWYgcmVzdWx0OgotICAgICAgICAgICAgcmFpc2UgZXJy
b3JzLkNvbm5lY3Rpb25FcnJvcigiZmFpbGVkIHRvIGNvbm5lY3QgdG8gJXM6JWQ6ICVzIiAlCi0g
ICAgICAgICAgICAgICAgICAgIChzZWxmLl9ob3N0LCBzZWxmLl9wb3J0LCBvcy5zdHJlcnJvcihy
ZXN1bHQpKSkKLSAgICAgICAgc2VsZi5fY29ubmVjdGVkID0gVHJ1ZQotCi0gICAgZGVmIF9mbHVz
aChzZWxmKToKLSAgICAgICAgIiIiU2VlIFNtYXJ0Q2xpZW50U3RyZWFtTWVkaXVtLl9mbHVzaCgp
LgotICAgICAgICAKLSAgICAgICAgRm9yIFRDUCB3ZSBkbyBubyBmbHVzaGluZy4gV2UgbWF5IHdh
bnQgdG8gdHVybiBvZmYgVENQX05PREVMQVkgYW5kIAotICAgICAgICBhZGQgYSBtZWFucyB0byBk
byBhIGZsdXNoLCBidXQgdGhhdCBjYW4gYmUgZG9uZSBpbiB0aGUgZnV0dXJlLgotICAgICAgICAi
IiIKLQotICAgIGRlZiBfcmVhZF9ieXRlcyhzZWxmLCBjb3VudCk6Ci0gICAgICAgICIiIlNlZSBT
bWFydENsaWVudE1lZGl1bS5yZWFkX2J5dGVzLiIiIgotICAgICAgICBpZiBub3Qgc2VsZi5fY29u
bmVjdGVkOgotICAgICAgICAgICAgcmFpc2UgZXJyb3JzLk1lZGl1bU5vdENvbm5lY3RlZChzZWxm
KQotICAgICAgICByZXR1cm4gc2VsZi5fc29ja2V0LnJlY3YoY291bnQpCi0KIAogY2xhc3MgU21h
cnRUQ1BUcmFuc3BvcnQoU21hcnRUcmFuc3BvcnQpOgogICAgICIiIkNvbm5lY3Rpb24gdG8gc21h
cnQgc2VydmVyIG92ZXIgcGxhaW4gdGNwLgoK

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200704090
... 44955-h3ijql5cvqxia4d4
# revision id: andrew.bennetts at canonical.com-20070409044955-h3ijql5cvqxia4d4
# sha1: 554c7c5099f5d074d16ed36b28f1d9914eb74e9f
# inventory sha1: 50c6074df587a46044715af127514ca088a1dd1b
# parent ids:
#   andrew.bennetts at canonical.com-20070406011930-wy4emdgu3yu527pm
# properties:
#   branch-nick: split-smart-part-1-rename

# message:
#   Move SmartTCPServer classes into bzrlib/smart/server.py
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2007-04-06 11:19:30.872999907 +1000

=== added directory bzrlib/smart // file-id:smart-20061101100241-u0wzhkl4sjwmuz
... hd-1
=== added file bzrlib/smart/__init__.py // file-id:__init__.py-20061101100249-8
... jwwl0d3jr080zim-1 // encoding:base64
LS0tIC9kZXYvbnVsbAorKysgYnpybGliL3NtYXJ0L19faW5pdF9fLnB5CkBAIC0wLDAgKzEsMTk0
IEBACisjIENvcHlyaWdodCAoQykgMjAwNiBDYW5vbmljYWwgTHRkCisjCisjIFRoaXMgcHJvZ3Jh
bSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5
CisjIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2Ug
YXMgcHVibGlzaGVkIGJ5CisjIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2
ZXJzaW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCisjIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVy
IHZlcnNpb24uCisjCisjIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0
aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAorIyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhv
dXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgorIyBNRVJDSEFOVEFCSUxJVFkgb3IgRklU
TkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisjIEdOVSBHZW5lcmFsIFB1
YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCisjCisjIFlvdSBzaG91bGQgaGF2ZSByZWNl
aXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCisjIGFsb25nIHdp
dGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCisjIEZv
dW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAw
MjExMS0xMzA3ICBVU0EKKworIiIiU21hcnQtc2VydmVyIHByb3RvY29sLCBjbGllbnQgYW5kIHNl
cnZlci4KKworUmVxdWVzdHMgYXJlIHNlbnQgYXMgYSBjb21tYW5kIGFuZCBsaXN0IG9mIGFyZ3Vt
ZW50cywgZm9sbG93ZWQgYnkgb3B0aW9uYWwKK2J1bGsgYm9keSBkYXRhLiAgUmVzcG9uc2VzIGFy
ZSBzaW1pbGFybHkgYSByZXNwb25zZSBhbmQgbGlzdCBvZiBhcmd1bWVudHMsCitmb2xsb3dlZCBi
eSBidWxrIGJvZHkgZGF0YS4gOjoKKworICBTRVAgOj0gJ1wwMDEnCisgICAgRmllbGRzIGFyZSBz
ZXBhcmF0ZWQgYnkgQ3RybC1BLgorICBCVUxLX0RBVEEgOj0gQ0hVTksgVFJBSUxFUgorICAgIENo
dW5rcyBjYW4gYmUgcmVwZWF0ZWQgYXMgbWFueSB0aW1lcyBhcyBuZWNlc3NhcnkuCisgIENIVU5L
IDo9IENIVU5LX0xFTiBDSFVOS19CT0RZCisgIENIVU5LX0xFTiA6PSBESUdJVCsgTkVXTElORQor
ICAgIEdpdmVzIHRoZSBudW1iZXIgb2YgYnl0ZXMgaW4gdGhlIGZvbGxvd2luZyBjaHVuay4KKyAg
Q0hVTktfQk9EWSA6PSBCWVRFW2NodW5rX2xlbl0KKyAgVFJBSUxFUiA6PSBTVUNDRVNTX1RSQUlM
RVIgfCBFUlJPUl9UUkFJTEVSCisgIFNVQ0NFU1NfVFJBSUxFUiA6PSAnZG9uZScgTkVXTElORQor
ICBFUlJPUl9UUkFJTEVSIDo9IAorCitQYXRocyBhcmUgcGFzc2VkIGFjcm9zcyB0aGUgbmV0d29y
ay4gIFRoZSBjbGllbnQgbmVlZHMgdG8gc2VlIGEgbmFtZXNwYWNlIHRoYXQKK2luY2x1ZGVzIGFu
eSByZXBvc2l0b3J5IHRoYXQgbWlnaHQgbmVlZCB0byBiZSByZWZlcmVuY2VkLCBhbmQgdGhlIGNs
aWVudCBuZWVkcwordG8ga25vdyBhYm91dCBhIHJvb3QgZGlyZWN0b3J5IGJleW9uZCB3aGljaCBp
dCBjYW5ub3QgYXNjZW5kLgorCitTZXJ2ZXJzIHJ1biBvdmVyIHNzaCB3aWxsIHR5cGljYWxseSB3
YW50IHRvIGJlIGFibGUgdG8gYWNjZXNzIGFueSBwYXRoIHRoZSB1c2VyIAorY2FuIGFjY2Vzcy4g
IFB1YmxpYyBzZXJ2ZXJzIG9uIHRoZSBvdGhlciBoYW5kICh3aGljaCBtaWdodCBiZSBvdmVyIGh0
dHAsIHNzaAorb3IgdGNwKSB3aWxsIHR5cGljYWxseSB3YW50IHRvIHJlc3RyaWN0IGFjY2VzcyB0
byBvbmx5IGEgcGFydGljdWxhciBkaXJlY3RvcnkgCithbmQgaXRzIGNoaWxkcmVuLCBzbyB3aWxs
IHdhbnQgdG8gZG8gYSBzb2Z0d2FyZSB2aXJ0dWFsIHJvb3QgYXQgdGhhdCBsZXZlbC4KK0luIG90
aGVyIHdvcmRzIHRoZXknbGwgd2FudCB0byByZXdyaXRlIGluY29taW5nIHBhdGhzIHRvIGJlIHVu
ZGVyIHRoYXQgbGV2ZWwKKyhhbmQgcHJldmVudCBlc2NhcGluZyB1c2luZyAuLi8gdHJpY2tzLikK
KworVVJMcyB0aGF0IGluY2x1ZGUgfiBzaG91bGQgcHJvYmFibHkgYmUgcGFzc2VkIGFjcm9zcyB0
byB0aGUgc2VydmVyIHZlcmJhdGltCithbmQgdGhlIHNlcnZlciBjYW4gZXhwYW5kIHRoZW0uICBU
aGlzIHdpbGwgcHJvYWJseSBub3QgYmUgbWVhbmluZ2Z1bCB3aGVuIAorbGltaXRlZCB0byBhIGRp
cmVjdG9yeT8KKworQXQgdGhlIGJvdHRvbSBsZXZlbCBzb2NrZXQsIHBpcGVzLCBIVFRQIHNlcnZl
ci4gIEZvciBzb2NrZXRzLCB3ZSBoYXZlIHRoZSBpZGVhCit0aGF0IHlvdSBoYXZlIG11bHRpcGxl
IHJlcXVlc3RzIGFuZCBnZXQgYSByZWFkIGVycm9yIGJlY2F1c2UgdGhlIG90aGVyIHNpZGUgZGlk
CitzaHV0ZG93bi4gIEZvciBwaXBlcyB3ZSBoYXZlIHJlYWQgcGlwZSB3aGljaCB3aWxsIGhhdmUg
YSB6ZXJvIHJlYWQgd2hpY2ggbWFya3MKK2VuZC1vZi1maWxlLiAgRm9yIEhUVFAgc2VydmVyIGVu
dmlyb25tZW50IHRoZXJlIGlzIG5vdCBlbmQtb2Ytc3RyZWFtIGJlY2F1c2UKK2VhY2ggcmVxdWVz
dCBjb21pbmcgaW50byB0aGUgc2VydmVyIGlzIGluZGVwZW5kZW50LgorCitTbyB3ZSBuZWVkIGEg
d3JhcHBlciBhcm91bmQgcGlwZXMgYW5kIHNvY2tldHMgdG8gc2VwZXJhdGUgb3V0IHJlcXVlc3Rz
IGZyb20KK3N1YnN0cmF0ZSBhbmQgdGhpcyB3aWxsIGdpdmUgdXMgYSBzaW5nbGUgbW9kZWwgd2hp
Y2ggaXMgY29uc2lzdCBmb3IgSFRUUCwKK3NvY2tldHMgYW5kIHBpcGVzLgorCitTZXJ2ZXItc2lk
ZQorLS0tLS0tLS0tLS0KKworIE1FRElVTSAgKGZhY3RvcnkgZm9yIHByb3RvY29sLCByZWFkcyBi
eXRlcyAmIHB1c2hlcyB0byBwcm90b2NvbCwKKyAgICAgICAgICB1c2VzIHByb3RvY29sIHRvIGRl
dGVjdCBlbmQtb2YtcmVxdWVzdCwgc2VuZHMgd3JpdHRlbgorICAgICAgICAgIGJ5dGVzIHRvIGNs
aWVudCkgZS5nLiBzb2NrZXQsIHBpcGUsIEhUVFAgcmVxdWVzdCBoYW5kbGVyLgorICBeCisgIHwg
Ynl0ZXMuCisgIHYKKworUFJPVE9DT0wgIChzZXJpYWxpemF0aW9uLCBkZXNlcmlhbGl6YXRpb24p
ICBhY2NlcHRzIGJ5dGVzIGZvciBvbmUKKyAgICAgICAgICByZXF1ZXN0LCBkZWNvZGVzIGFjY29y
ZGluZyB0byBpbnRlcm5hbCBzdGF0ZSwgcHVzaGVzCisgICAgICAgICAgc3RydWN0dXJlZCBkYXRh
IHRvIGhhbmRsZXIuICBhY2NlcHRzIHN0cnVjdHVyZWQgZGF0YSBmcm9tCisgICAgICAgICAgaGFu
ZGxlciBhbmQgZW5jb2RlcyBhbmQgd3JpdGVzIHRvIHRoZSBtZWRpdW0uICBmYWN0b3J5IGZvcgor
ICAgICAgICAgIGhhbmRsZXIuCisgIF4KKyAgfCBzdHJ1Y3R1cmVkIGRhdGEKKyAgdgorCitIQU5E
TEVSICAgKGRvbWFpbiBsb2dpYykgYWNjZXB0cyBzdHJ1Y3R1cmVkIGRhdGEsIG9wZXJhdGVzIHN0
YXRlCisgICAgICAgICAgbWFjaGluZSB1bnRpbCB0aGUgcmVxdWVzdCBjYW4gYmUgc2F0aXNmaWVk
LAorICAgICAgICAgIHNlbmRzIHN0cnVjdHVyZWQgZGF0YSB0byB0aGUgcHJvdG9jb2wuCisKKwor
Q2xpZW50LXNpZGUKKy0tLS0tLS0tLS0tCisKKyBDTElFTlQgICAgICAgICAgICAgZG9tYWluIGxv
Z2ljLCBhY2NlcHRzIGRvbWFpbiByZXF1ZXN0cywgZ2VuZXJhdGVkIHN0cnVjdHVyZWQKKyAgICAg
ICAgICAgICAgICAgICAgZGF0YSwgcmVhZHMgc3RydWN0dXJlZCBkYXRhIGZyb20gcmVzcG9uc2Vz
IGFuZCB0dXJucyBpbnRvCisgICAgICAgICAgICAgICAgICAgIGRvbWFpbiBkYXRhLiAgU2VuZHMg
c3RydWN0dXJlZCBkYXRhIHRvIHRoZSBwcm90b2NvbC4KKyAgICAgICAgICAgICAgICAgICAgT3Bl
cmF0ZXMgc3RhdGUgbWFjaGluZXMgdW50aWwgdGhlIHJlcXVlc3QgY2FuIGJlIGRlbGl2ZXJlZAor
ICAgICAgICAgICAgICAgICAgICAoZS5nLiByZWFkaW5nIGZyb20gYSBidW5kbGUgZ2VuZXJhdGVk
IGluIGJ6cmxpYiB0byBkZWxpdmVyIGEKKyAgICAgICAgICAgICAgICAgICAgY29tcGxldGUgcmVx
dWVzdCkuCisKKyAgICAgICAgICAgICAgICAgICAgUG9zc2libHkgdGhpcyBzaG91bGQganVzdCBi
ZSBSZW1vdGVCenJEaXIsIFJlbW90ZVRyYW5zcG9ydCwKKyAgICAgICAgICAgICAgICAgICAgLi4u
CisgIF4KKyAgfCBzdHJ1Y3R1cmVkIGRhdGEKKyAgdgorCitQUk9UT0NPTCAgKHNlcmlhbGl6YXRp
b24sIGRlc2VyaWFsaXphdGlvbikgIGFjY2VwdHMgc3RydWN0dXJlZCBkYXRhIGZvciBvbmUKKyAg
ICAgICAgICByZXF1ZXN0LCBlbmNvZGVzIGFuZCB3cml0ZXMgdG8gdGhlIG1lZGl1bS4gIFJlYWRz
IGJ5dGVzIGZyb20gdGhlCisgICAgICAgICAgbWVkaXVtLCBkZWNvZGVzIGFuZCBhbGxvd3MgdGhl
IGNsaWVudCB0byByZWFkIHN0cnVjdHVyZWQgZGF0YS4KKyAgXgorICB8IGJ5dGVzLgorICB2CisK
KyBNRURJVU0gIChhY2NlcHRzIGJ5dGVzIGZyb20gdGhlIHByb3RvY29sICYgZGVsaXZlcnMgdG8g
dGhlIHJlbW90ZSBzZXJ2ZXIuCisgICAgICAgICAgQWxsb3dzIHRoZSBwb3RvY29sIHRvIHJlYWQg
Ynl0ZXMgZS5nLiBzb2NrZXQsIHBpcGUsIEhUVFAgcmVxdWVzdC4KKyIiIgorCisjIFRPRE86IF90
cmFuc2xhdGVfZXJyb3Igc2hvdWxkIGJlIG9uIHRoZSBjbGllbnQsIG5vdCB0aGUgdHJhbnNwb3J0
IGJlY2F1c2UKKyMgICAgIGVycm9yIGNvZGluZyBpcyB3aXJlIHByb3RvY29sIHNwZWNpZmljLgor
CisjIFRPRE86IEEgcGxhaW4gaW50ZWdlciBmcm9tIHF1ZXJ5X3ZlcnNpb24gaXMgdG9vIHNpbXBs
ZTsgc2hvdWxkIGdpdmUgc29tZQorIyBjYXBhYmlsaXRpZXMgdG9vPworCisjIFRPRE86IFNlcnZl
ciBzaG91bGQgcHJvYmFibHkgY2F0Y2ggZXhjZXB0aW9ucyB3aXRoaW4gaXRzZWxmIGFuZCBzZW5k
IHRoZW0KKyMgYmFjayBhY3Jvc3MgdGhlIG5ldHdvcmsuICAoQnV0IHNob3VsZG4ndCBjYXRjaCBL
ZXlib2FyZEludGVycnVwdCBldGMpCisjIEFsc28gbmVlZHMgdG8gc29tZWhvdyByZXBvcnQgcHJv
dG9jb2wgZXJyb3JzIGxpa2UgYmFkIHJlcXVlc3RzLiAgTmVlZCB0bworIyBjb25zaWRlciBob3cg
d2UnbGwgaGFuZGxlIGVycm9yIHJlcG9ydGluZywgZS5nLiBpZiB3ZSBnZXQgaGFsZndheSB0aHJv
dWdoIGEKKyMgYnVsayB0cmFuc2ZlciBhbmQgdGhlbiBzb21ldGhpbmcgZ29lcyB3cm9uZy4KKwor
IyBUT0RPOiBTdGFuZGFyZCBtYXJrZXIgYXQgc3RhcnQgb2YgcmVxdWVzdC9yZXNwb25zZSBsaW5l
cz8KKworIyBUT0RPOiBNYWtlIGVhY2ggcmVxdWVzdCBhbmQgcmVzcG9uc2Ugc2VsZi12YWxpZGF0
YWJsZSwgZS5nLiB3aXRoIGNoZWNrc3Vtcy4KKyMKKyMgVE9ETzogZ2V0L3B1dCBvYmplY3RzIGNv
dWxkIGJlIGNoYW5nZWQgdG8gZ3JhZHVhbGx5IHJlYWQgYmFjayB0aGUgZGF0YSBhcyBpdAorIyBj
b21lcyBhY3Jvc3MgdGhlIG5ldHdvcmsKKyMKKyMgVE9ETzogV2hhdCBzaG91bGQgdGhlIHNlcnZl
ciBkbyBpZiBpdCBoaXRzIGFuIGVycm9yIGFuZCBoYXMgdG8gdGVybWluYXRlPworIworIyBUT0RP
OiBpcyBpdCB1c2VmdWwgdG8gYWxsb3cgbXVsdGlwbGUgY2h1bmtzIGluIHRoZSBidWxrIGRhdGE/
CisjCisjIFRPRE86IElmIHdlIGdldCBhbiBleGNlcHRpb24gZHVyaW5nIHRyYW5zbWlzc2lvbiBv
ZiBidWxrIGRhdGEgd2UgY2FuJ3QganVzdAorIyBlbWl0IHRoZSBleGNlcHRpb24gYmVjYXVzZSBp
dCB3b24ndCBiZSBzZWVuLgorIyAgIEpvaG4gcHJvcG9zZXM6ICBJIHRoaW5rIGl0IHdvdWxkIGJl
IHdvcnRod2hpbGUgdG8gaGF2ZSBhIGhlYWRlciBvbiBlYWNoCisjICAgY2h1bmssIHRoYXQgaW5k
aWNhdGVzIGl0IGlzIGFub3RoZXIgY2h1bmsuIFRoZW4geW91IGNhbiBzZW5kIGFuICdlcnJvcicK
KyMgICBjaHVuayBhcyBsb25nIGFzIHlvdSBmaW5pc2ggdGhlIHByZXZpb3VzIGNodW5rLgorIwor
IyBUT0RPOiBDbG9uZSBtZXRob2Qgb24gVHJhbnNwb3J0OyBzaG91bGQgd29yayB1cCB0b3dhcmRz
IHBhcmVudCBkaXJlY3Rvcnk7CisjIHVuY2xlYXIgaG93IHRoaXMgc2hvdWxkIGJlIHN0b3JlZCBv
ciBjb21tdW5pY2F0ZWQgdG8gdGhlIHNlcnZlci4uLiBtYXliZQorIyBqdXN0IHBhc3MgaXQgb24g
YWxsIHJlbGV2YW50IHJlcXVlc3RzPworIworIyBUT0RPOiBCZXR0ZXIgbmFtZSB0aGFuIGNsb25l
KCkgZm9yIGNoYW5naW5nIGJldHdlZW4gZGlyZWN0b3JpZXMuICBIb3cgYWJvdXQKKyMgb3Blbl9k
aXIgb3IgY2hhbmdlX2RpciBvciBjaGRpcj8KKyMKKyMgVE9ETzogSXMgaXQgcmVhbGx5IGdvb2Qg
dG8gaGF2ZSB0aGUgbm90aW9uIG9mIGN1cnJlbnQgZGlyZWN0b3J5IHdpdGhpbiB0aGUKKyMgY29u
bmVjdGlvbj8gIFBlcmhhcHMgYWxsIFRyYW5zcG9ydHMgc2hvdWxkIGZhY3RvciBvdXQgYSBjb21t
b24gY29ubmVjdGlvbgorIyBmcm9tIHRoZSB0aGluZyB0aGF0IGhhcyB0aGUgZGlyZWN0b3J5IGNv
bnRleHQ/CisjCisjIFRPRE86IFB1bGwgbW9yZSB0aGluZ3MgY29tbW9uIHRvIHNmdHAgYW5kIHNz
aCB0byBhIGhpZ2hlciBsZXZlbC4KKyMKKyMgVE9ETzogVGhlIHNlcnZlciB0aGF0IG1hbmFnZXMg
YSBjb25uZWN0aW9uIHNob3VsZCBiZSBxdWl0ZSBzbWFsbCBhbmQgcmV0YWluCisjIG1pbmltdW0g
c3RhdGUgYmVjYXVzZSBlYWNoIG9mIHRoZSByZXF1ZXN0cyBhcmUgc3VwcG9zZWQgdG8gYmUgc3Rh
dGVsZXNzLgorIyBUaGVuIHdlIGNhbiB3cml0ZSBhbm90aGVyIGltcGxlbWVudGF0aW9uIHRoYXQg
bWFwcyB0byBodHRwLgorIworIyBUT0RPOiBXaGF0IHRvIGRvIHdoZW4gYSBjbGllbnQgY29ubmVj
dGlvbiBpcyBnYXJiYWdlIGNvbGxlY3RlZD8gIE1heWJlIGp1c3QKKyMgYWJydXB0bHkgZHJvcCB0
aGUgY29ubmVjdGlvbj8KKyMKKyMgVE9ETzogU2VydmVyIGluIHNvbWUgY2FzZXMgd2lsbCBuZWVk
IHRvIHJlc3RyaWN0IGFjY2VzcyB0byBmaWxlcyBvdXRzaWRlIG9mCisjIGEgcGFydGljdWxhciBy
b290IGRpcmVjdG9yeS4gIExvY2FsVHJhbnNwb3J0IGRvZXNuJ3QgZG8gYW55dGhpbmcgdG8gc3Rv
cCB5b3UKKyMgYXNjZW5kaW5nIGFib3ZlIHRoZSBiYXNlIGRpcmVjdG9yeSwgc28gd2UgbmVlZCB0
byBwcmV2ZW50IHBhdGhzCisjIGNvbnRhaW5pbmcgJy4uJyBpbiBlaXRoZXIgdGhlIHNlcnZlciBv
ciB0cmFuc3BvcnQgbGF5ZXJzLiAgKEFsc28gbmVlZCB0bworIyBjb25zaWRlciB3aGF0IGhhcHBl
bnMgaWYgc29tZW9uZSBjcmVhdGVzIGEgc3ltbGluayBwb2ludGluZyBvdXRzaWRlIHRoZSAKKyMg
ZGlyZWN0b3J5IHRyZWUuLi4pCisjCisjIFRPRE86IFNlcnZlciBzaG91bGQgcmViYXNlIGFic29s
dXRlIHBhdGhzIGNvbWluZyBhY3Jvc3MgdGhlIG5ldHdvcmsgdG8gcHV0CisjIHRoZW0gdW5kZXIg
dGhlIHZpcnR1YWwgcm9vdCwgaWYgb25lIGlzIGluIHVzZS4gIExvY2FsVHJhbnNwb3J0IGN1cnJl
bnRseQorIyBkb2Vzbid0IGRvIHRoYXQ7IGlmIHlvdSBnaXZlIGl0IGFuIGFic29sdXRlIHBhdGgg
aXQganVzdCB1c2VzIGl0LgorIyAKKyMgWFhYOiBBcmd1bWVudHMgY2FuJ3QgY29udGFpbiBuZXds
aW5lcyBvciBhc2NpaTsgcG9zc2libHkgd2Ugc2hvdWxkIGUuZy4KKyMgdXJsZXNjYXBlIHRoZW0g
aW5zdGVhZC4gIEluZGVlZCBwb3NzaWJseSB0aGlzIHNob3VsZCBqdXN0IGxpdGVyYWxseSBiZQor
IyBodHRwLW92ZXItc3NoLgorIworIyBGSVhNRTogVGhpcyB0cmFuc3BvcnQsIHdpdGggc2V2ZXJh
bCBvdGhlcnMsIGhhcyBpbXBlcmZlY3QgaGFuZGxpbmcgb2YgcGF0aHMKKyMgd2l0aGluIHVybHMu
ICBJdCdkIHByb2JhYmx5IGJlIGJldHRlciBmb3IgIi4uIiBmcm9tIGEgcm9vdCB0byByYWlzZSBh
biBlcnJvcgorIyByYXRoZXIgdGhhbiByZXR1cm4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHdlIGRv
IGF0IHByZXNlbnQuCisjCisjIFRPRE86IFJhdGhlciB0aGFuIHdvcmtpbmcgYXQgdGhlIFRyYW5z
cG9ydCBsYXllciB3ZSB3YW50IGEgQnJhbmNoLAorIyBSZXBvc2l0b3J5IG9yIEJ6ckRpciBvYmpl
Y3RzIHRoYXQgdGFsayB0byBhIHNlcnZlci4KKyMKKyMgVE9ETzogUHJvYmFibHkgd2FudCBzb21l
IHdheSBmb3Igc2VydmVyIGNvbW1hbmRzIHRvIGdyYWR1YWxseSBwcm9kdWNlIGJvZHkKKyMgZGF0
YSByYXRoZXIgdGhhbiBwYXNzaW5nIGl0IGFzIGEgc3RyaW5nOyB0aGV5IGNvdWxkIHBlcmhhcHMg
cGFzcyBhbgorIyBpdGVyYXRvci1saWtlIGNhbGxiYWNrIHRoYXQgd2lsbCBncmFkdWFsbHkgeWll
bGQgZGF0YTsgaXQgcHJvYmFibHkgbmVlZHMgYQorIyBjbG9zZSgpIG1ldGhvZCB0aGF0IHdpbGwg
YWx3YXlzIGJlIGNsb3NlZCB0byBkbyBhbnkgbmVjZXNzYXJ5IGNsZWFudXAuCisjCisjIFRPRE86
IFNwbGl0IHRoZSBhY3R1YWwgc21hcnQgc2VydmVyIGZyb20gdGhlIHNzaCBlbmNvZGluZyBvZiBp
dC4KKyMKKyMgVE9ETzogUGVyaGFwcyBzdXBwb3J0IGZpbGUtbGV2ZWwgcmVhZHdyaXRlIG9wZXJh
dGlvbnMgb3ZlciB0aGUgdHJhbnNwb3J0CisjIHRvby4KKyMKKyMgVE9ETzogU21hcnRCenJEaXIg
Y2xhc3MsIHByb3h5aW5nIGFsbCBCcmFuY2ggZXRjIG1ldGhvZHMgYWNyb3NzIHRvIGFub3RoZXIK
KyMgYnJhbmNoIGRvaW5nIGZpbGUtbGV2ZWwgb3BlcmF0aW9ucy4KKyMKCg==

=== added file bzrlib/smart/medium.py // file-id:medium.py-20061103051856-rgu2h
... uy59fkz902q-1 // encoding:base64

=== added file bzrlib/smart/protocol.py // file-id:protocol.py-20061108035435-o
... t0lstk2590yqhzr-1 // encoding:base64

=== added file bzrlib/smart/request.py // file-id:request.py-20061108095550-gun
... adhxmzkdjfeek-1 // encoding:base64

=== added file bzrlib/smart/server.py // file-id:server.py-20061110062051-chzu1
... 0y32vx8gvur-1 // encoding:base64
LS0tIC9kZXYvbnVsbAorKysgYnpybGliL3NtYXJ0L3NlcnZlci5weQpAQCAtMCwwICsxLDEzOSBA
QAorIyBDb3B5cmlnaHQgKEMpIDIwMDYsIDIwMDcgQ2Fub25pY2FsIEx0ZAorIworIyBUaGlzIHBy
b2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1v
ZGlmeQorIyBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl
bnNlIGFzIHB1Ymxpc2hlZCBieQorIyB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRo
ZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorIyAoYXQgeW91ciBvcHRpb24pIGFueSBs
YXRlciB2ZXJzaW9uLgorIworIyBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhv
cGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyMgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3
aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKKyMgTUVSQ0hBTlRBQklMSVRZIG9y
IEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQorIyBHTlUgR2VuZXJh
bCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorIworIyBZb3Ugc2hvdWxkIGhhdmUg
cmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZQorIyBhbG9u
ZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQor
IyBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UsIFN1aXRlIDMzMCwgQm9zdG9uLCBN
QSAgMDIxMTEtMTMwNyAgVVNBCisKKyIiIlNlcnZlciBmb3Igc21hcnQtc2VydmVyIHByb3RvY29s
LiIiIgorCitpbXBvcnQgc29ja2V0CitpbXBvcnQgb3MKK2ltcG9ydCB0aHJlYWRpbmcKKworZnJv
bSBienJsaWIuc21hcnQgaW1wb3J0IG1lZGl1bQorZnJvbSBienJsaWIgaW1wb3J0ICgKKyAgICB0
cmFjZSwKKyAgICB0cmFuc3BvcnQsCisgICAgdXJsdXRpbHMsCispCitmcm9tIGJ6cmxpYi50cmFu
c3BvcnQucmVtb3RlIGltcG9ydCBTbWFydFNlcnZlclNvY2tldFN0cmVhbU1lZGl1bQorCisKK2Ns
YXNzIFNtYXJ0VENQU2VydmVyKG9iamVjdCk6CisgICAgIiIiTGlzdGVucyBvbiBhIFRDUCBzb2Nr
ZXQgYW5kIGFjY2VwdHMgY29ubmVjdGlvbnMgZnJvbSBzbWFydCBjbGllbnRzIiIiCisKKyAgICBk
ZWYgX19pbml0X18oc2VsZiwgYmFja2luZ190cmFuc3BvcnQsIGhvc3Q9JzEyNy4wLjAuMScsIHBv
cnQ9MCk6CisgICAgICAgICIiIkNvbnN0cnVjdCBhIG5ldyBzZXJ2ZXIuCisKKyAgICAgICAgVG8g
YWN0dWFsbHkgc3RhcnQgaXQgcnVubmluZywgY2FsbCBlaXRoZXIgc3RhcnRfYmFja2dyb3VuZF90
aHJlYWQgb3IKKyAgICAgICAgc2VydmUuCisKKyAgICAgICAgOnBhcmFtIGhvc3Q6IE5hbWUgb2Yg
dGhlIGludGVyZmFjZSB0byBsaXN0ZW4gb24uCisgICAgICAgIDpwYXJhbSBwb3J0OiBUQ1AgcG9y
dCB0byBsaXN0ZW4gb24sIG9yIDAgdG8gYWxsb2NhdGUgYSB0cmFuc2llbnQgcG9ydC4KKyAgICAg
ICAgIiIiCisgICAgICAgIHNlbGYuX3NlcnZlcl9zb2NrZXQgPSBzb2NrZXQuc29ja2V0KCkKKyAg
ICAgICAgc2VsZi5fc2VydmVyX3NvY2tldC5iaW5kKChob3N0LCBwb3J0KSkKKyAgICAgICAgc2Vs
Zi5wb3J0ID0gc2VsZi5fc2VydmVyX3NvY2tldC5nZXRzb2NrbmFtZSgpWzFdCisgICAgICAgIHNl
bGYuX3NlcnZlcl9zb2NrZXQubGlzdGVuKDEpCisgICAgICAgIHNlbGYuX3NlcnZlcl9zb2NrZXQu
c2V0dGltZW91dCgxKQorICAgICAgICBzZWxmLmJhY2tpbmdfdHJhbnNwb3J0ID0gYmFja2luZ190
cmFuc3BvcnQKKworICAgIGRlZiBzZXJ2ZShzZWxmKToKKyAgICAgICAgIyBsZXQgY29ubmVjdGlv
bnMgdGltZW91dCBzbyB0aGF0IHdlIGdldCBhIGNoYW5jZSB0byB0ZXJtaW5hdGUKKyAgICAgICAg
IyBLZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSBleGNlcHRpb25zIHdlIHdhbnQgdG8gY2F0Y2ggYmVj
YXVzZSB0aGUgc29ja2V0CisgICAgICAgICMgbW9kdWxlJ3MgZ2xvYmFscyBnZXQgc2V0IHRvIE5v
bmUgZHVyaW5nIGludGVycHJldGVyIHNodXRkb3duLgorICAgICAgICBmcm9tIHNvY2tldCBpbXBv
cnQgdGltZW91dCBhcyBzb2NrZXRfdGltZW91dAorICAgICAgICBmcm9tIHNvY2tldCBpbXBvcnQg
ZXJyb3IgYXMgc29ja2V0X2Vycm9yCisgICAgICAgIHNlbGYuX3Nob3VsZF90ZXJtaW5hdGUgPSBG
YWxzZQorICAgICAgICB3aGlsZSBub3Qgc2VsZi5fc2hvdWxkX3Rlcm1pbmF0ZToKKyAgICAgICAg
ICAgIHRyeToKKyAgICAgICAgICAgICAgICBzZWxmLmFjY2VwdF9hbmRfc2VydmUoKQorICAgICAg
ICAgICAgZXhjZXB0IHNvY2tldF90aW1lb3V0OgorICAgICAgICAgICAgICAgICMganVzdCBjaGVj
ayBpZiB3ZSdyZSBhc2tlZCB0byBzdG9wCisgICAgICAgICAgICAgICAgcGFzcworICAgICAgICAg
ICAgZXhjZXB0IHNvY2tldF9lcnJvciwgZToKKyAgICAgICAgICAgICAgICB0cmFjZS53YXJuaW5n
KCJjbGllbnQgZGlzY29ubmVjdGVkOiAlcyIsIGUpCisgICAgICAgICAgICAgICAgcGFzcworCisg
ICAgZGVmIGdldF91cmwoc2VsZik6CisgICAgICAgICIiIlJldHVybiB0aGUgdXJsIG9mIHRoZSBz
ZXJ2ZXIiIiIKKyAgICAgICAgcmV0dXJuICJienI6Ly8lczolZC8iICUgc2VsZi5fc2VydmVyX3Nv
Y2tldC5nZXRzb2NrbmFtZSgpCisKKyAgICBkZWYgYWNjZXB0X2FuZF9zZXJ2ZShzZWxmKToKKyAg
ICAgICAgY29ubiwgY2xpZW50X2FkZHIgPSBzZWxmLl9zZXJ2ZXJfc29ja2V0LmFjY2VwdCgpCisg
ICAgICAgICMgRm9yIFdJTjMyLCB3aGVyZSB0aGUgdGltZW91dCB2YWx1ZSBmcm9tIHRoZSBsaXN0
ZW5pbmcgc29ja2V0CisgICAgICAgICMgcHJvcG9nYXRlcyB0byB0aGUgbmV3bHkgYWNjZXB0ZWQg
c29ja2V0LgorICAgICAgICBjb25uLnNldGJsb2NraW5nKFRydWUpCisgICAgICAgIGNvbm4uc2V0
c29ja29wdChzb2NrZXQuSVBQUk9UT19UQ1AsIHNvY2tldC5UQ1BfTk9ERUxBWSwgMSkKKyAgICAg
ICAgaGFuZGxlciA9IFNtYXJ0U2VydmVyU29ja2V0U3RyZWFtTWVkaXVtKGNvbm4sIHNlbGYuYmFj
a2luZ190cmFuc3BvcnQpCisgICAgICAgIGNvbm5lY3Rpb25fdGhyZWFkID0gdGhyZWFkaW5nLlRo
cmVhZChOb25lLCBoYW5kbGVyLnNlcnZlLCBuYW1lPSdzbWFydC1zZXJ2ZXItY2hpbGQnKQorICAg
ICAgICBjb25uZWN0aW9uX3RocmVhZC5zZXREYWVtb24oVHJ1ZSkKKyAgICAgICAgY29ubmVjdGlv
bl90aHJlYWQuc3RhcnQoKQorCisgICAgZGVmIHN0YXJ0X2JhY2tncm91bmRfdGhyZWFkKHNlbGYp
OgorICAgICAgICBzZWxmLl9zZXJ2ZXJfdGhyZWFkID0gdGhyZWFkaW5nLlRocmVhZChOb25lLAor
ICAgICAgICAgICAgICAgIHNlbGYuc2VydmUsCisgICAgICAgICAgICAgICAgbmFtZT0nc2VydmVy
LScgKyBzZWxmLmdldF91cmwoKSkKKyAgICAgICAgc2VsZi5fc2VydmVyX3RocmVhZC5zZXREYWVt
b24oVHJ1ZSkKKyAgICAgICAgc2VsZi5fc2VydmVyX3RocmVhZC5zdGFydCgpCisKKyAgICBkZWYg
c3RvcF9iYWNrZ3JvdW5kX3RocmVhZChzZWxmKToKKyAgICAgICAgc2VsZi5fc2hvdWxkX3Rlcm1p
bmF0ZSA9IFRydWUKKyAgICAgICAgIyBBdCBvbmUgcG9pbnQgd2Ugd291bGQgd2FpdCB0byBqb2lu
IHRoZSB0aHJlYWRzIGhlcmUsIGJ1dCBpdCBsb29rcworICAgICAgICAjIGxpa2UgdGhleSBkb24n
dCBhY3R1YWxseSBleGl0LiAgU28gbm93IHdlIGp1c3QgbGVhdmUgdGhlbSBydW5uaW5nCisgICAg
ICAgICMgYW5kIGV4cGVjdCB0byB0ZXJtaW5hdGUgdGhlIHByb2Nlc3MuIC0tIG1icCAyMDA3MDIx
NQorICAgICAgICAjIHNlbGYuX3NlcnZlcl9zb2NrZXQuY2xvc2UoKQorICAgICAgICAjIyBzeXMu
c3RkZXJyLndyaXRlKCJ3YWl0aW5nIGZvciBzZXJ2ZXIgdGhyZWFkIHRvIGZpbmlzaC4uLiIpCisg
ICAgICAgICMjIHNlbGYuX3NlcnZlcl90aHJlYWQuam9pbigpCisKKworY2xhc3MgU21hcnRUQ1BT
ZXJ2ZXJfZm9yX3Rlc3RpbmcoU21hcnRUQ1BTZXJ2ZXIpOgorICAgICIiIlNlcnZlciBzdWl0YWJs
ZSBmb3IgdXNlIGJ5IHRyYW5zcG9ydCB0ZXN0cy4KKyAgICAKKyAgICBUaGlzIHNlcnZlciBpcyBi
YWNrZWQgYnkgdGhlIHByb2Nlc3MncyBjd2QuCisgICAgIiIiCisKKyAgICBkZWYgX19pbml0X18o
c2VsZik6CisgICAgICAgIHNlbGYuX2hvbWVkaXIgPSB1cmx1dGlscy5sb2NhbF9wYXRoX3RvX3Vy
bChvcy5nZXRjd2QoKSlbNzpdCisgICAgICAgICMgVGhlIHNlcnZlciBpcyBzZXQgdXAgYnkgZGVm
YXVsdCBsaWtlIGZvciBzc2ggYWNjZXNzOiB0aGUgY2xpZW50CisgICAgICAgICMgcGFzc2VzIGZp
bGVzeXN0ZW0tYWJzb2x1dGUgcGF0aHM7IHRoZXJlZm9yZSB0aGUgc2VydmVyIG11c3QgbG9vawor
ICAgICAgICAjIHRoZW0gdXAgcmVsYXRpdmUgdG8gdGhlIHJvb3QgZGlyZWN0b3J5LiAgaXQgbWln
aHQgYmUgYmV0dGVyIHRvIGFjdAorICAgICAgICAjIGEgcHVibGljIHNlcnZlciBhbmQgaGF2ZSB0
aGUgc2VydmVyIHJld3JpdGUgcGF0aHMgaW50byB0aGUgdGVzdAorICAgICAgICAjIGRpcmVjdG9y
eS4KKyAgICAgICAgU21hcnRUQ1BTZXJ2ZXIuX19pbml0X18oc2VsZiwKKyAgICAgICAgICAgIHRy
YW5zcG9ydC5nZXRfdHJhbnNwb3J0KHVybHV0aWxzLmxvY2FsX3BhdGhfdG9fdXJsKCcvJykpKQor
ICAgICAgICAKKyAgICBkZWYgZ2V0X2JhY2tpbmdfdHJhbnNwb3J0KHNlbGYsIGJhY2tpbmdfdHJh
bnNwb3J0X3NlcnZlcik6CisgICAgICAgICIiIkdldCBhIGJhY2tpbmcgdHJhbnNwb3J0IGZyb20g
YSBzZXJ2ZXIgd2UgYXJlIGRlY29yYXRpbmcuIiIiCisgICAgICAgIHJldHVybiB0cmFuc3BvcnQu
Z2V0X3RyYW5zcG9ydChiYWNraW5nX3RyYW5zcG9ydF9zZXJ2ZXIuZ2V0X3VybCgpKQorCisgICAg
ZGVmIHNldFVwKHNlbGYsIGJhY2tpbmdfdHJhbnNwb3J0X3NlcnZlcj1Ob25lKToKKyAgICAgICAg
IiIiU2V0IHVwIHNlcnZlciBmb3IgdGVzdGluZyIiIgorICAgICAgICBmcm9tIGJ6cmxpYi50cmFu
c3BvcnQuY2hyb290IGltcG9ydCBUZXN0aW5nQ2hyb290U2VydmVyCisgICAgICAgIGlmIGJhY2tp
bmdfdHJhbnNwb3J0X3NlcnZlciBpcyBOb25lOgorICAgICAgICAgICAgZnJvbSBienJsaWIudHJh
bnNwb3J0LmxvY2FsIGltcG9ydCBMb2NhbFVSTFNlcnZlcgorICAgICAgICAgICAgYmFja2luZ190
cmFuc3BvcnRfc2VydmVyID0gTG9jYWxVUkxTZXJ2ZXIoKQorICAgICAgICBzZWxmLmNocm9vdF9z
ZXJ2ZXIgPSBUZXN0aW5nQ2hyb290U2VydmVyKCkKKyAgICAgICAgc2VsZi5jaHJvb3Rfc2VydmVy
LnNldFVwKGJhY2tpbmdfdHJhbnNwb3J0X3NlcnZlcikKKyAgICAgICAgc2VsZi5iYWNraW5nX3Ry
YW5zcG9ydCA9IHRyYW5zcG9ydC5nZXRfdHJhbnNwb3J0KAorICAgICAgICAgICAgc2VsZi5jaHJv
b3Rfc2VydmVyLmdldF91cmwoKSkKKyAgICAgICAgc2VsZi5zdGFydF9iYWNrZ3JvdW5kX3RocmVh
ZCgpCisKKyAgICBkZWYgdGVhckRvd24oc2VsZik6CisgICAgICAgIHNlbGYuc3RvcF9iYWNrZ3Jv
dW5kX3RocmVhZCgpCisKKyAgICBkZWYgZ2V0X2JvZ3VzX3VybChzZWxmKToKKyAgICAgICAgIiIi
UmV0dXJuIGEgVVJMIHdoaWNoIHdpbGwgZmFpbCB0byBjb25uZWN0IiIiCisgICAgICAgIHJldHVy
biAnYnpyOi8vMTI3LjAuMC4xOjEvJworCisKCg==

=== modified file bzrlib/builtins.py // encoding:base64
LS0tIGJ6cmxpYi9idWlsdGlucy5weQorKysgYnpybGliL2J1aWx0aW5zLnB5CkBAIC0zMjI0LDcg
KzMyMjQsOCBAQAogICAgICAgICBdCiAKICAgICBkZWYgcnVuKHNlbGYsIHBvcnQ9Tm9uZSwgaW5l
dD1GYWxzZSwgZGlyZWN0b3J5PU5vbmUsIGFsbG93X3dyaXRlcz1GYWxzZSk6Ci0gICAgICAgIGZy
b20gYnpybGliLnRyYW5zcG9ydCBpbXBvcnQgc21hcnQKKyAgICAgICAgZnJvbSBienJsaWIuc21h
cnQgaW1wb3J0IHNlcnZlcgorICAgICAgICBmcm9tIGJ6cmxpYi50cmFuc3BvcnQgaW1wb3J0IHJl
bW90ZQogICAgICAgICBmcm9tIGJ6cmxpYi50cmFuc3BvcnQgaW1wb3J0IGdldF90cmFuc3BvcnQK
ICAgICAgICAgaWYgZGlyZWN0b3J5IGlzIE5vbmU6CiAgICAgICAgICAgICBkaXJlY3RvcnkgPSBv
cy5nZXRjd2QoKQpAQCAtMzIzMywxMCArMzIzNCwxMCBAQAogICAgICAgICAgICAgdXJsID0gJ3Jl
YWRvbmx5KycgKyB1cmwKICAgICAgICAgdCA9IGdldF90cmFuc3BvcnQodXJsKQogICAgICAgICBp
ZiBpbmV0OgotICAgICAgICAgICAgc2VydmVyID0gc21hcnQuU21hcnRTZXJ2ZXJQaXBlU3RyZWFt
TWVkaXVtKHN5cy5zdGRpbiwgc3lzLnN0ZG91dCwgdCkKKyAgICAgICAgICAgIHNtYXJ0X3NlcnZl
ciA9IHJlbW90ZS5TbWFydFNlcnZlclBpcGVTdHJlYW1NZWRpdW0oc3lzLnN0ZGluLCBzeXMuc3Rk
b3V0LCB0KQogICAgICAgICBlbHNlOgogICAgICAgICAgICAgaWYgcG9ydCBpcyBOb25lOgotICAg
ICAgICAgICAgICAgIHBvcnQgPSBzbWFydC5CWlJfREVGQVVMVF9QT1JUCisgICAgICAgICAgICAg
ICAgcG9ydCA9IHJlbW90ZS5CWlJfREVGQVVMVF9QT1JUCiAgICAgICAgICAgICAgICAgaG9zdCA9
ICcxMjcuMC4wLjEnCiAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgIGlmICc6JyBp
biBwb3J0OgpAQCAtMzI0NCwxMCArMzI0NSwxMCBAQAogICAgICAgICAgICAgICAgIGVsc2U6CiAg
ICAgICAgICAgICAgICAgICAgIGhvc3QgPSAnMTI3LjAuMC4xJwogICAgICAgICAgICAgICAgIHBv
cnQgPSBpbnQocG9ydCkKLSAgICAgICAgICAgIHNlcnZlciA9IHNtYXJ0LlNtYXJ0VENQU2VydmVy
KHQsIGhvc3Q9aG9zdCwgcG9ydD1wb3J0KQotICAgICAgICAgICAgcHJpbnQgJ2xpc3RlbmluZyBv
biBwb3J0OiAnLCBzZXJ2ZXIucG9ydAorICAgICAgICAgICAgc21hcnRfc2VydmVyID0gc2VydmVy
LlNtYXJ0VENQU2VydmVyKHQsIGhvc3Q9aG9zdCwgcG9ydD1wb3J0KQorICAgICAgICAgICAgcHJp
bnQgJ2xpc3RlbmluZyBvbiBwb3J0OiAnLCBzbWFydF9zZXJ2ZXIucG9ydAogICAgICAgICAgICAg
c3lzLnN0ZG91dC5mbHVzaCgpCi0gICAgICAgIHNlcnZlci5zZXJ2ZSgpCisgICAgICAgIHNtYXJ0
X3NlcnZlci5zZXJ2ZSgpCiAKIGNsYXNzIGNtZF9qb2luKENvbW1hbmQpOgogICAgICIiIkNvbWJp
bmUgYSBzdWJ0cmVlIGludG8gaXRzIGNvbnRhaW5pbmcgdHJlZS4KCg==

=== modified file bzrlib/tests/test_smart_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NtYXJ0X3RyYW5zcG9ydC5weQorKysgYnpybGliL3Rlc3Rz
L3Rlc3Rfc21hcnRfdHJhbnNwb3J0LnB5CkBAIC0zMCw2ICszMCw3IEBACiAgICAgICAgIHRlc3Rz
LAogICAgICAgICB1cmx1dGlscywKICAgICAgICAgKQorZnJvbSBienJsaWIuc21hcnQgaW1wb3J0
IHNlcnZlcgogZnJvbSBienJsaWIudGVzdHMuSFRUUFRlc3RVdGlsIGltcG9ydCAoCiAgICAgICAg
IEhUVFBTZXJ2ZXJXaXRoU21hcnRzLAogICAgICAgICBTbWFydFJlcXVlc3RIYW5kbGVyLApAQCAt
NTIxLDcgKzUyMiw3IEBACiAgICAgICAgICMgdGhlIGRlZmF1bHQgb3IgYSBwYXJhbWV0ZXJpemVk
IGNsYXNzLCBidXQgcmF0aGVyIHVzZSB0aGUKICAgICAgICAgIyBUZXN0Q2FzZVdpdGhUcmFuc3Bv
cnQgaW5mcmFzdHJ1Y3R1cmUgdG8gc2V0IHVwIGEgc21hcnQgc2VydmVyIGFuZAogICAgICAgICAj
IHRyYW5zcG9ydC4KLSAgICAgICAgc2VsZi50cmFuc3BvcnRfc2VydmVyID0gc21hcnQuU21hcnRU
Q1BTZXJ2ZXJfZm9yX3Rlc3RpbmcKKyAgICAgICAgc2VsZi50cmFuc3BvcnRfc2VydmVyID0gc2Vy
dmVyLlNtYXJ0VENQU2VydmVyX2Zvcl90ZXN0aW5nCiAKICAgICBkZWYgdGVzdF9wbGF1c2libGVf
dXJsKHNlbGYpOgogICAgICAgICBzZWxmLmFzc2VydF8oc2VsZi5nZXRfdXJsKCkuc3RhcnRzd2l0
aCgnYnpyOi8vJykpCkBAIC03NzQsMTAgKzc3NSwxMCBAQAogICAgICAgICBjbGFzcyBGbGFreVRy
YW5zcG9ydChvYmplY3QpOgogICAgICAgICAgICAgZGVmIGdldF9ieXRlcyhzZWxmLCBwYXRoKToK
ICAgICAgICAgICAgICAgICByYWlzZSBFeGNlcHRpb24oInNvbWUgcmFuZG9tIGV4Y2VwdGlvbiBm
cm9tIGluc2lkZSBzZXJ2ZXIiKQotICAgICAgICBzZXJ2ZXIgPSBzbWFydC5TbWFydFRDUFNlcnZl
cihiYWNraW5nX3RyYW5zcG9ydD1GbGFreVRyYW5zcG9ydCgpKQotICAgICAgICBzZXJ2ZXIuc3Rh
cnRfYmFja2dyb3VuZF90aHJlYWQoKQorICAgICAgICBzbWFydF9zZXJ2ZXIgPSBzZXJ2ZXIuU21h
cnRUQ1BTZXJ2ZXIoYmFja2luZ190cmFuc3BvcnQ9Rmxha3lUcmFuc3BvcnQoKSkKKyAgICAgICAg
c21hcnRfc2VydmVyLnN0YXJ0X2JhY2tncm91bmRfdGhyZWFkKCkKICAgICAgICAgdHJ5OgotICAg
ICAgICAgICAgdHJhbnNwb3J0ID0gc21hcnQuU21hcnRUQ1BUcmFuc3BvcnQoc2VydmVyLmdldF91
cmwoKSkKKyAgICAgICAgICAgIHRyYW5zcG9ydCA9IHNtYXJ0LlNtYXJ0VENQVHJhbnNwb3J0KHNt
YXJ0X3NlcnZlci5nZXRfdXJsKCkpCiAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAg
dHJhbnNwb3J0LmdldCgnc29tZXRoaW5nJykKICAgICAgICAgICAgIGV4Y2VwdCBlcnJvcnMuVHJh
bnNwb3J0RXJyb3IsIGU6CkBAIC03ODUsNyArNzg2LDcgQEAKICAgICAgICAgICAgIGVsc2U6CiAg
ICAgICAgICAgICAgICAgc2VsZi5mYWlsKCJnZXQgZGlkIG5vdCByYWlzZSBleHBlY3RlZCBlcnJv
ciIpCiAgICAgICAgIGZpbmFsbHk6Ci0gICAgICAgICAgICBzZXJ2ZXIuc3RvcF9iYWNrZ3JvdW5k
X3RocmVhZCgpCisgICAgICAgICAgICBzbWFydF9zZXJ2ZXIuc3RvcF9iYWNrZ3JvdW5kX3RocmVh
ZCgpCiAKIAogY2xhc3MgU21hcnRUQ1BUZXN0cyh0ZXN0cy5UZXN0Q2FzZSk6CkBAIC04MDYsNyAr
ODA3LDcgQEAKICAgICAgICAgaWYgcmVhZG9ubHk6CiAgICAgICAgICAgICBzZWxmLnJlYWxfYmFj
a2luZ190cmFuc3BvcnQgPSBzZWxmLmJhY2tpbmdfdHJhbnNwb3J0CiAgICAgICAgICAgICBzZWxm
LmJhY2tpbmdfdHJhbnNwb3J0ID0gZ2V0X3RyYW5zcG9ydCgicmVhZG9ubHkrIiArIHNlbGYuYmFj
a2luZ190cmFuc3BvcnQuYWJzcGF0aCgnLicpKQotICAgICAgICBzZWxmLnNlcnZlciA9IHNtYXJ0
LlNtYXJ0VENQU2VydmVyKHNlbGYuYmFja2luZ190cmFuc3BvcnQpCisgICAgICAgIHNlbGYuc2Vy
dmVyID0gc2VydmVyLlNtYXJ0VENQU2VydmVyKHNlbGYuYmFja2luZ190cmFuc3BvcnQpCiAgICAg
ICAgIHNlbGYuc2VydmVyLnN0YXJ0X2JhY2tncm91bmRfdGhyZWFkKCkKICAgICAgICAgc2VsZi50
cmFuc3BvcnQgPSBzbWFydC5TbWFydFRDUFRyYW5zcG9ydChzZWxmLnNlcnZlci5nZXRfdXJsKCkp
CiAKCg==

=== modified file bzrlib/transport/remote.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvcmVtb3RlLnB5CisrKyBienJsaWIvdHJhbnNwb3J0L3JlbW90
ZS5weQpAQCAtMTQsMTg2ICsxNCw2IEBACiAjIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBu
b3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAjIEZvdW5kYXRpb24sIEluYy4sIDU5IFRl
bXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKIAotIiIi
U21hcnQtc2VydmVyIHByb3RvY29sLCBjbGllbnQgYW5kIHNlcnZlci4KLQotUmVxdWVzdHMgYXJl
IHNlbnQgYXMgYSBjb21tYW5kIGFuZCBsaXN0IG9mIGFyZ3VtZW50cywgZm9sbG93ZWQgYnkgb3B0
aW9uYWwKLWJ1bGsgYm9keSBkYXRhLiAgUmVzcG9uc2VzIGFyZSBzaW1pbGFybHkgYSByZXNwb25z
ZSBhbmQgbGlzdCBvZiBhcmd1bWVudHMsCi1mb2xsb3dlZCBieSBidWxrIGJvZHkgZGF0YS4gOjoK
LQotICBTRVAgOj0gJ1wwMDEnCi0gICAgRmllbGRzIGFyZSBzZXBhcmF0ZWQgYnkgQ3RybC1BLgot
ICBCVUxLX0RBVEEgOj0gQ0hVTksgVFJBSUxFUgotICAgIENodW5rcyBjYW4gYmUgcmVwZWF0ZWQg
YXMgbWFueSB0aW1lcyBhcyBuZWNlc3NhcnkuCi0gIENIVU5LIDo9IENIVU5LX0xFTiBDSFVOS19C
T0RZCi0gIENIVU5LX0xFTiA6PSBESUdJVCsgTkVXTElORQotICAgIEdpdmVzIHRoZSBudW1iZXIg
b2YgYnl0ZXMgaW4gdGhlIGZvbGxvd2luZyBjaHVuay4KLSAgQ0hVTktfQk9EWSA6PSBCWVRFW2No
dW5rX2xlbl0KLSAgVFJBSUxFUiA6PSBTVUNDRVNTX1RSQUlMRVIgfCBFUlJPUl9UUkFJTEVSCi0g
IFNVQ0NFU1NfVFJBSUxFUiA6PSAnZG9uZScgTkVXTElORQotICBFUlJPUl9UUkFJTEVSIDo9IAot
Ci1QYXRocyBhcmUgcGFzc2VkIGFjcm9zcyB0aGUgbmV0d29yay4gIFRoZSBjbGllbnQgbmVlZHMg
dG8gc2VlIGEgbmFtZXNwYWNlIHRoYXQKLWluY2x1ZGVzIGFueSByZXBvc2l0b3J5IHRoYXQgbWln
aHQgbmVlZCB0byBiZSByZWZlcmVuY2VkLCBhbmQgdGhlIGNsaWVudCBuZWVkcwotdG8ga25vdyBh
Ym91dCBhIHJvb3QgZGlyZWN0b3J5IGJleW9uZCB3aGljaCBpdCBjYW5ub3QgYXNjZW5kLgotCi1T
ZXJ2ZXJzIHJ1biBvdmVyIHNzaCB3aWxsIHR5cGljYWxseSB3YW50IHRvIGJlIGFibGUgdG8gYWNj
ZXNzIGFueSBwYXRoIHRoZSB1c2VyIAotY2FuIGFjY2Vzcy4gIFB1YmxpYyBzZXJ2ZXJzIG9uIHRo
ZSBvdGhlciBoYW5kICh3aGljaCBtaWdodCBiZSBvdmVyIGh0dHAsIHNzaAotb3IgdGNwKSB3aWxs
IHR5cGljYWxseSB3YW50IHRvIHJlc3RyaWN0IGFjY2VzcyB0byBvbmx5IGEgcGFydGljdWxhciBk
aXJlY3RvcnkgCi1hbmQgaXRzIGNoaWxkcmVuLCBzbyB3aWxsIHdhbnQgdG8gZG8gYSBzb2Z0d2Fy
ZSB2aXJ0dWFsIHJvb3QgYXQgdGhhdCBsZXZlbC4KLUluIG90aGVyIHdvcmRzIHRoZXknbGwgd2Fu
dCB0byByZXdyaXRlIGluY29taW5nIHBhdGhzIHRvIGJlIHVuZGVyIHRoYXQgbGV2ZWwKLShhbmQg
cHJldmVudCBlc2NhcGluZyB1c2luZyAuLi8gdHJpY2tzLikKLQotVVJMcyB0aGF0IGluY2x1ZGUg
fiBzaG91bGQgcHJvYmFibHkgYmUgcGFzc2VkIGFjcm9zcyB0byB0aGUgc2VydmVyIHZlcmJhdGlt
Ci1hbmQgdGhlIHNlcnZlciBjYW4gZXhwYW5kIHRoZW0uICBUaGlzIHdpbGwgcHJvYWJseSBub3Qg
YmUgbWVhbmluZ2Z1bCB3aGVuIAotbGltaXRlZCB0byBhIGRpcmVjdG9yeT8KLQotQXQgdGhlIGJv
dHRvbSBsZXZlbCBzb2NrZXQsIHBpcGVzLCBIVFRQIHNlcnZlci4gIEZvciBzb2NrZXRzLCB3ZSBo
YXZlIHRoZSBpZGVhCi10aGF0IHlvdSBoYXZlIG11bHRpcGxlIHJlcXVlc3RzIGFuZCBnZXQgYSBy
ZWFkIGVycm9yIGJlY2F1c2UgdGhlIG90aGVyIHNpZGUgZGlkCi1zaHV0ZG93bi4gIEZvciBwaXBl
cyB3ZSBoYXZlIHJlYWQgcGlwZSB3aGljaCB3aWxsIGhhdmUgYSB6ZXJvIHJlYWQgd2hpY2ggbWFy
a3MKLWVuZC1vZi1maWxlLiAgRm9yIEhUVFAgc2VydmVyIGVudmlyb25tZW50IHRoZXJlIGlzIG5v
dCBlbmQtb2Ytc3RyZWFtIGJlY2F1c2UKLWVhY2ggcmVxdWVzdCBjb21pbmcgaW50byB0aGUgc2Vy
dmVyIGlzIGluZGVwZW5kZW50LgotCi1TbyB3ZSBuZWVkIGEgd3JhcHBlciBhcm91bmQgcGlwZXMg
YW5kIHNvY2tldHMgdG8gc2VwZXJhdGUgb3V0IHJlcXVlc3RzIGZyb20KLXN1YnN0cmF0ZSBhbmQg
dGhpcyB3aWxsIGdpdmUgdXMgYSBzaW5nbGUgbW9kZWwgd2hpY2ggaXMgY29uc2lzdCBmb3IgSFRU
UCwKLXNvY2tldHMgYW5kIHBpcGVzLgotCi1TZXJ2ZXItc2lkZQotLS0tLS0tLS0tLS0KLQotIE1F
RElVTSAgKGZhY3RvcnkgZm9yIHByb3RvY29sLCByZWFkcyBieXRlcyAmIHB1c2hlcyB0byBwcm90
b2NvbCwKLSAgICAgICAgICB1c2VzIHByb3RvY29sIHRvIGRldGVjdCBlbmQtb2YtcmVxdWVzdCwg
c2VuZHMgd3JpdHRlbgotICAgICAgICAgIGJ5dGVzIHRvIGNsaWVudCkgZS5nLiBzb2NrZXQsIHBp
cGUsIEhUVFAgcmVxdWVzdCBoYW5kbGVyLgotICBeCi0gIHwgYnl0ZXMuCi0gIHYKLQotUFJPVE9D
T0wgIChzZXJpYWxpemF0aW9uLCBkZXNlcmlhbGl6YXRpb24pICBhY2NlcHRzIGJ5dGVzIGZvciBv
bmUKLSAgICAgICAgICByZXF1ZXN0LCBkZWNvZGVzIGFjY29yZGluZyB0byBpbnRlcm5hbCBzdGF0
ZSwgcHVzaGVzCi0gICAgICAgICAgc3RydWN0dXJlZCBkYXRhIHRvIGhhbmRsZXIuICBhY2NlcHRz
IHN0cnVjdHVyZWQgZGF0YSBmcm9tCi0gICAgICAgICAgaGFuZGxlciBhbmQgZW5jb2RlcyBhbmQg
d3JpdGVzIHRvIHRoZSBtZWRpdW0uICBmYWN0b3J5IGZvcgotICAgICAgICAgIGhhbmRsZXIuCi0g
IF4KLSAgfCBzdHJ1Y3R1cmVkIGRhdGEKLSAgdgotCi1IQU5ETEVSICAgKGRvbWFpbiBsb2dpYykg
YWNjZXB0cyBzdHJ1Y3R1cmVkIGRhdGEsIG9wZXJhdGVzIHN0YXRlCi0gICAgICAgICAgbWFjaGlu
ZSB1bnRpbCB0aGUgcmVxdWVzdCBjYW4gYmUgc2F0aXNmaWVkLAotICAgICAgICAgIHNlbmRzIHN0
cnVjdHVyZWQgZGF0YSB0byB0aGUgcHJvdG9jb2wuCi0KLQotQ2xpZW50LXNpZGUKLS0tLS0tLS0t
LS0tCi0KLSBDTElFTlQgICAgICAgICAgICAgZG9tYWluIGxvZ2ljLCBhY2NlcHRzIGRvbWFpbiBy
ZXF1ZXN0cywgZ2VuZXJhdGVkIHN0cnVjdHVyZWQKLSAgICAgICAgICAgICAgICAgICAgZGF0YSwg
cmVhZHMgc3RydWN0dXJlZCBkYXRhIGZyb20gcmVzcG9uc2VzIGFuZCB0dXJucyBpbnRvCi0gICAg
ICAgICAgICAgICAgICAgIGRvbWFpbiBkYXRhLiAgU2VuZHMgc3RydWN0dXJlZCBkYXRhIHRvIHRo
ZSBwcm90b2NvbC4KLSAgICAgICAgICAgICAgICAgICAgT3BlcmF0ZXMgc3RhdGUgbWFjaGluZXMg
dW50aWwgdGhlIHJlcXVlc3QgY2FuIGJlIGRlbGl2ZXJlZAotICAgICAgICAgICAgICAgICAgICAo
ZS5nLiByZWFkaW5nIGZyb20gYSBidW5kbGUgZ2VuZXJhdGVkIGluIGJ6cmxpYiB0byBkZWxpdmVy
IGEKLSAgICAgICAgICAgICAgICAgICAgY29tcGxldGUgcmVxdWVzdCkuCi0KLSAgICAgICAgICAg
ICAgICAgICAgUG9zc2libHkgdGhpcyBzaG91bGQganVzdCBiZSBSZW1vdGVCenJEaXIsIFJlbW90
ZVRyYW5zcG9ydCwKLSAgICAgICAgICAgICAgICAgICAgLi4uCi0gIF4KLSAgfCBzdHJ1Y3R1cmVk
IGRhdGEKLSAgdgotCi1QUk9UT0NPTCAgKHNlcmlhbGl6YXRpb24sIGRlc2VyaWFsaXphdGlvbikg
IGFjY2VwdHMgc3RydWN0dXJlZCBkYXRhIGZvciBvbmUKLSAgICAgICAgICByZXF1ZXN0LCBlbmNv
ZGVzIGFuZCB3cml0ZXMgdG8gdGhlIG1lZGl1bS4gIFJlYWRzIGJ5dGVzIGZyb20gdGhlCi0gICAg
ICAgICAgbWVkaXVtLCBkZWNvZGVzIGFuZCBhbGxvd3MgdGhlIGNsaWVudCB0byByZWFkIHN0cnVj
dHVyZWQgZGF0YS4KLSAgXgotICB8IGJ5dGVzLgotICB2Ci0KLSBNRURJVU0gIChhY2NlcHRzIGJ5
dGVzIGZyb20gdGhlIHByb3RvY29sICYgZGVsaXZlcnMgdG8gdGhlIHJlbW90ZSBzZXJ2ZXIuCi0g
ICAgICAgICAgQWxsb3dzIHRoZSBwb3RvY29sIHRvIHJlYWQgYnl0ZXMgZS5nLiBzb2NrZXQsIHBp
cGUsIEhUVFAgcmVxdWVzdC4KLSIiIgotCi0KLSMgVE9ETzogX3RyYW5zbGF0ZV9lcnJvciBzaG91
bGQgYmUgb24gdGhlIGNsaWVudCwgbm90IHRoZSB0cmFuc3BvcnQgYmVjYXVzZQotIyAgICAgZXJy
b3IgY29kaW5nIGlzIHdpcmUgcHJvdG9jb2wgc3BlY2lmaWMuCi0KLSMgVE9ETzogQSBwbGFpbiBp
bnRlZ2VyIGZyb20gcXVlcnlfdmVyc2lvbiBpcyB0b28gc2ltcGxlOyBzaG91bGQgZ2l2ZSBzb21l
Ci0jIGNhcGFiaWxpdGllcyB0b28/Ci0KLSMgVE9ETzogU2VydmVyIHNob3VsZCBwcm9iYWJseSBj
YXRjaCBleGNlcHRpb25zIHdpdGhpbiBpdHNlbGYgYW5kIHNlbmQgdGhlbQotIyBiYWNrIGFjcm9z
cyB0aGUgbmV0d29yay4gIChCdXQgc2hvdWxkbid0IGNhdGNoIEtleWJvYXJkSW50ZXJydXB0IGV0
YykKLSMgQWxzbyBuZWVkcyB0byBzb21laG93IHJlcG9ydCBwcm90b2NvbCBlcnJvcnMgbGlrZSBi
YWQgcmVxdWVzdHMuICBOZWVkIHRvCi0jIGNvbnNpZGVyIGhvdyB3ZSdsbCBoYW5kbGUgZXJyb3Ig
cmVwb3J0aW5nLCBlLmcuIGlmIHdlIGdldCBoYWxmd2F5IHRocm91Z2ggYQotIyBidWxrIHRyYW5z
ZmVyIGFuZCB0aGVuIHNvbWV0aGluZyBnb2VzIHdyb25nLgotCi0jIFRPRE86IFN0YW5kYXJkIG1h
cmtlciBhdCBzdGFydCBvZiByZXF1ZXN0L3Jlc3BvbnNlIGxpbmVzPwotCi0jIFRPRE86IE1ha2Ug
ZWFjaCByZXF1ZXN0IGFuZCByZXNwb25zZSBzZWxmLXZhbGlkYXRhYmxlLCBlLmcuIHdpdGggY2hl
Y2tzdW1zLgotIwotIyBUT0RPOiBnZXQvcHV0IG9iamVjdHMgY291bGQgYmUgY2hhbmdlZCB0byBn
cmFkdWFsbHkgcmVhZCBiYWNrIHRoZSBkYXRhIGFzIGl0Ci0jIGNvbWVzIGFjcm9zcyB0aGUgbmV0
d29yawotIwotIyBUT0RPOiBXaGF0IHNob3VsZCB0aGUgc2VydmVyIGRvIGlmIGl0IGhpdHMgYW4g
ZXJyb3IgYW5kIGhhcyB0byB0ZXJtaW5hdGU/Ci0jCi0jIFRPRE86IGlzIGl0IHVzZWZ1bCB0byBh
bGxvdyBtdWx0aXBsZSBjaHVua3MgaW4gdGhlIGJ1bGsgZGF0YT8KLSMKLSMgVE9ETzogSWYgd2Ug
Z2V0IGFuIGV4Y2VwdGlvbiBkdXJpbmcgdHJhbnNtaXNzaW9uIG9mIGJ1bGsgZGF0YSB3ZSBjYW4n
dCBqdXN0Ci0jIGVtaXQgdGhlIGV4Y2VwdGlvbiBiZWNhdXNlIGl0IHdvbid0IGJlIHNlZW4uCi0j
ICAgSm9obiBwcm9wb3NlczogIEkgdGhpbmsgaXQgd291bGQgYmUgd29ydGh3aGlsZSB0byBoYXZl
IGEgaGVhZGVyIG9uIGVhY2gKLSMgICBjaHVuaywgdGhhdCBpbmRpY2F0ZXMgaXQgaXMgYW5vdGhl
ciBjaHVuay4gVGhlbiB5b3UgY2FuIHNlbmQgYW4gJ2Vycm9yJwotIyAgIGNodW5rIGFzIGxvbmcg
YXMgeW91IGZpbmlzaCB0aGUgcHJldmlvdXMgY2h1bmsuCi0jCi0jIFRPRE86IENsb25lIG1ldGhv
ZCBvbiBUcmFuc3BvcnQ7IHNob3VsZCB3b3JrIHVwIHRvd2FyZHMgcGFyZW50IGRpcmVjdG9yeTsK
LSMgdW5jbGVhciBob3cgdGhpcyBzaG91bGQgYmUgc3RvcmVkIG9yIGNvbW11bmljYXRlZCB0byB0
aGUgc2VydmVyLi4uIG1heWJlCi0jIGp1c3QgcGFzcyBpdCBvbiBhbGwgcmVsZXZhbnQgcmVxdWVz
dHM/Ci0jCi0jIFRPRE86IEJldHRlciBuYW1lIHRoYW4gY2xvbmUoKSBmb3IgY2hhbmdpbmcgYmV0
d2VlbiBkaXJlY3Rvcmllcy4gIEhvdyBhYm91dAotIyBvcGVuX2RpciBvciBjaGFuZ2VfZGlyIG9y
IGNoZGlyPwotIwotIyBUT0RPOiBJcyBpdCByZWFsbHkgZ29vZCB0byBoYXZlIHRoZSBub3Rpb24g
b2YgY3VycmVudCBkaXJlY3Rvcnkgd2l0aGluIHRoZQotIyBjb25uZWN0aW9uPyAgUGVyaGFwcyBh
bGwgVHJhbnNwb3J0cyBzaG91bGQgZmFjdG9yIG91dCBhIGNvbW1vbiBjb25uZWN0aW9uCi0jIGZy
b20gdGhlIHRoaW5nIHRoYXQgaGFzIHRoZSBkaXJlY3RvcnkgY29udGV4dD8KLSMKLSMgVE9ETzog
UHVsbCBtb3JlIHRoaW5ncyBjb21tb24gdG8gc2Z0cCBhbmQgc3NoIHRvIGEgaGlnaGVyIGxldmVs
LgotIwotIyBUT0RPOiBUaGUgc2VydmVyIHRoYXQgbWFuYWdlcyBhIGNvbm5lY3Rpb24gc2hvdWxk
IGJlIHF1aXRlIHNtYWxsIGFuZCByZXRhaW4KLSMgbWluaW11bSBzdGF0ZSBiZWNhdXNlIGVhY2gg
b2YgdGhlIHJlcXVlc3RzIGFyZSBzdXBwb3NlZCB0byBiZSBzdGF0ZWxlc3MuCi0jIFRoZW4gd2Ug
Y2FuIHdyaXRlIGFub3RoZXIgaW1wbGVtZW50YXRpb24gdGhhdCBtYXBzIHRvIGh0dHAuCi0jCi0j
IFRPRE86IFdoYXQgdG8gZG8gd2hlbiBhIGNsaWVudCBjb25uZWN0aW9uIGlzIGdhcmJhZ2UgY29s
bGVjdGVkPyAgTWF5YmUganVzdAotIyBhYnJ1cHRseSBkcm9wIHRoZSBjb25uZWN0aW9uPwotIwot
IyBUT0RPOiBTZXJ2ZXIgaW4gc29tZSBjYXNlcyB3aWxsIG5lZWQgdG8gcmVzdHJpY3QgYWNjZXNz
IHRvIGZpbGVzIG91dHNpZGUgb2YKLSMgYSBwYXJ0aWN1bGFyIHJvb3QgZGlyZWN0b3J5LiAgTG9j
YWxUcmFuc3BvcnQgZG9lc24ndCBkbyBhbnl0aGluZyB0byBzdG9wIHlvdQotIyBhc2NlbmRpbmcg
YWJvdmUgdGhlIGJhc2UgZGlyZWN0b3J5LCBzbyB3ZSBuZWVkIHRvIHByZXZlbnQgcGF0aHMKLSMg
Y29udGFpbmluZyAnLi4nIGluIGVpdGhlciB0aGUgc2VydmVyIG9yIHRyYW5zcG9ydCBsYXllcnMu
ICAoQWxzbyBuZWVkIHRvCi0jIGNvbnNpZGVyIHdoYXQgaGFwcGVucyBpZiBzb21lb25lIGNyZWF0
ZXMgYSBzeW1saW5rIHBvaW50aW5nIG91dHNpZGUgdGhlIAotIyBkaXJlY3RvcnkgdHJlZS4uLikK
LSMKLSMgVE9ETzogU2VydmVyIHNob3VsZCByZWJhc2UgYWJzb2x1dGUgcGF0aHMgY29taW5nIGFj
cm9zcyB0aGUgbmV0d29yayB0byBwdXQKLSMgdGhlbSB1bmRlciB0aGUgdmlydHVhbCByb290LCBp
ZiBvbmUgaXMgaW4gdXNlLiAgTG9jYWxUcmFuc3BvcnQgY3VycmVudGx5Ci0jIGRvZXNuJ3QgZG8g
dGhhdDsgaWYgeW91IGdpdmUgaXQgYW4gYWJzb2x1dGUgcGF0aCBpdCBqdXN0IHVzZXMgaXQuCi0j
IAotIyBYWFg6IEFyZ3VtZW50cyBjYW4ndCBjb250YWluIG5ld2xpbmVzIG9yIGFzY2lpOyBwb3Nz
aWJseSB3ZSBzaG91bGQgZS5nLgotIyB1cmxlc2NhcGUgdGhlbSBpbnN0ZWFkLiAgSW5kZWVkIHBv
c3NpYmx5IHRoaXMgc2hvdWxkIGp1c3QgbGl0ZXJhbGx5IGJlCi0jIGh0dHAtb3Zlci1zc2guCi0j
Ci0jIEZJWE1FOiBUaGlzIHRyYW5zcG9ydCwgd2l0aCBzZXZlcmFsIG90aGVycywgaGFzIGltcGVy
ZmVjdCBoYW5kbGluZyBvZiBwYXRocwotIyB3aXRoaW4gdXJscy4gIEl0J2QgcHJvYmFibHkgYmUg
YmV0dGVyIGZvciAiLi4iIGZyb20gYSByb290IHRvIHJhaXNlIGFuIGVycm9yCi0jIHJhdGhlciB0
aGFuIHJldHVybiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgd2UgZG8gYXQgcHJlc2VudC4KLSMKLSMg
VE9ETzogUmF0aGVyIHRoYW4gd29ya2luZyBhdCB0aGUgVHJhbnNwb3J0IGxheWVyIHdlIHdhbnQg
YSBCcmFuY2gsCi0jIFJlcG9zaXRvcnkgb3IgQnpyRGlyIG9iamVjdHMgdGhhdCB0YWxrIHRvIGEg
c2VydmVyLgotIwotIyBUT0RPOiBQcm9iYWJseSB3YW50IHNvbWUgd2F5IGZvciBzZXJ2ZXIgY29t
bWFuZHMgdG8gZ3JhZHVhbGx5IHByb2R1Y2UgYm9keQotIyBkYXRhIHJhdGhlciB0aGFuIHBhc3Np
bmcgaXQgYXMgYSBzdHJpbmc7IHRoZXkgY291bGQgcGVyaGFwcyBwYXNzIGFuCi0jIGl0ZXJhdG9y
LWxpa2UgY2FsbGJhY2sgdGhhdCB3aWxsIGdyYWR1YWxseSB5aWVsZCBkYXRhOyBpdCBwcm9iYWJs
eSBuZWVkcyBhCi0jIGNsb3NlKCkgbWV0aG9kIHRoYXQgd2lsbCBhbHdheXMgYmUgY2xvc2VkIHRv
IGRvIGFueSBuZWNlc3NhcnkgY2xlYW51cC4KLSMKLSMgVE9ETzogU3BsaXQgdGhlIGFjdHVhbCBz
bWFydCBzZXJ2ZXIgZnJvbSB0aGUgc3NoIGVuY29kaW5nIG9mIGl0LgotIwotIyBUT0RPOiBQZXJo
YXBzIHN1cHBvcnQgZmlsZS1sZXZlbCByZWFkd3JpdGUgb3BlcmF0aW9ucyBvdmVyIHRoZSB0cmFu
c3BvcnQKLSMgdG9vLgotIwotIyBUT0RPOiBTbWFydEJ6ckRpciBjbGFzcywgcHJveHlpbmcgYWxs
IEJyYW5jaCBldGMgbWV0aG9kcyBhY3Jvc3MgdG8gYW5vdGhlcgotIyBicmFuY2ggZG9pbmcgZmls
ZS1sZXZlbCBvcGVyYXRpb25zLgotIwotCiBmcm9tIGNTdHJpbmdJTyBpbXBvcnQgU3RyaW5nSU8K
IGltcG9ydCBvcwogaW1wb3J0IHNvY2tldApAQCAtODE5LDExNCArNjM5LDYgQEAKICAgICAgICAg
ICAgICAgICByYWlzZQogCiAKLWNsYXNzIFNtYXJ0VENQU2VydmVyKG9iamVjdCk6Ci0gICAgIiIi
TGlzdGVucyBvbiBhIFRDUCBzb2NrZXQgYW5kIGFjY2VwdHMgY29ubmVjdGlvbnMgZnJvbSBzbWFy
dCBjbGllbnRzIiIiCi0KLSAgICBkZWYgX19pbml0X18oc2VsZiwgYmFja2luZ190cmFuc3BvcnQs
IGhvc3Q9JzEyNy4wLjAuMScsIHBvcnQ9MCk6Ci0gICAgICAgICIiIkNvbnN0cnVjdCBhIG5ldyBz
ZXJ2ZXIuCi0KLSAgICAgICAgVG8gYWN0dWFsbHkgc3RhcnQgaXQgcnVubmluZywgY2FsbCBlaXRo
ZXIgc3RhcnRfYmFja2dyb3VuZF90aHJlYWQgb3IKLSAgICAgICAgc2VydmUuCi0KLSAgICAgICAg
OnBhcmFtIGhvc3Q6IE5hbWUgb2YgdGhlIGludGVyZmFjZSB0byBsaXN0ZW4gb24uCi0gICAgICAg
IDpwYXJhbSBwb3J0OiBUQ1AgcG9ydCB0byBsaXN0ZW4gb24sIG9yIDAgdG8gYWxsb2NhdGUgYSB0
cmFuc2llbnQgcG9ydC4KLSAgICAgICAgIiIiCi0gICAgICAgIHNlbGYuX3NlcnZlcl9zb2NrZXQg
PSBzb2NrZXQuc29ja2V0KCkKLSAgICAgICAgc2VsZi5fc2VydmVyX3NvY2tldC5iaW5kKChob3N0
LCBwb3J0KSkKLSAgICAgICAgc2VsZi5wb3J0ID0gc2VsZi5fc2VydmVyX3NvY2tldC5nZXRzb2Nr
bmFtZSgpWzFdCi0gICAgICAgIHNlbGYuX3NlcnZlcl9zb2NrZXQubGlzdGVuKDEpCi0gICAgICAg
IHNlbGYuX3NlcnZlcl9zb2NrZXQuc2V0dGltZW91dCgxKQotICAgICAgICBzZWxmLmJhY2tpbmdf
dHJhbnNwb3J0ID0gYmFja2luZ190cmFuc3BvcnQKLQotICAgIGRlZiBzZXJ2ZShzZWxmKToKLSAg
ICAgICAgIyBsZXQgY29ubmVjdGlvbnMgdGltZW91dCBzbyB0aGF0IHdlIGdldCBhIGNoYW5jZSB0
byB0ZXJtaW5hdGUKLSAgICAgICAgIyBLZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSBleGNlcHRpb25z
IHdlIHdhbnQgdG8gY2F0Y2ggYmVjYXVzZSB0aGUgc29ja2V0Ci0gICAgICAgICMgbW9kdWxlJ3Mg
Z2xvYmFscyBnZXQgc2V0IHRvIE5vbmUgZHVyaW5nIGludGVycHJldGVyIHNodXRkb3duLgotICAg
ICAgICBmcm9tIHNvY2tldCBpbXBvcnQgdGltZW91dCBhcyBzb2NrZXRfdGltZW91dAotICAgICAg
ICBmcm9tIHNvY2tldCBpbXBvcnQgZXJyb3IgYXMgc29ja2V0X2Vycm9yCi0gICAgICAgIHNlbGYu
X3Nob3VsZF90ZXJtaW5hdGUgPSBGYWxzZQotICAgICAgICB3aGlsZSBub3Qgc2VsZi5fc2hvdWxk
X3Rlcm1pbmF0ZToKLSAgICAgICAgICAgIHRyeToKLSAgICAgICAgICAgICAgICBzZWxmLmFjY2Vw
dF9hbmRfc2VydmUoKQotICAgICAgICAgICAgZXhjZXB0IHNvY2tldF90aW1lb3V0OgotICAgICAg
ICAgICAgICAgICMganVzdCBjaGVjayBpZiB3ZSdyZSBhc2tlZCB0byBzdG9wCi0gICAgICAgICAg
ICAgICAgcGFzcwotICAgICAgICAgICAgZXhjZXB0IHNvY2tldF9lcnJvciwgZToKLSAgICAgICAg
ICAgICAgICB0cmFjZS53YXJuaW5nKCJjbGllbnQgZGlzY29ubmVjdGVkOiAlcyIsIGUpCi0gICAg
ICAgICAgICAgICAgcGFzcwotCi0gICAgZGVmIGdldF91cmwoc2VsZik6Ci0gICAgICAgICIiIlJl
dHVybiB0aGUgdXJsIG9mIHRoZSBzZXJ2ZXIiIiIKLSAgICAgICAgcmV0dXJuICJienI6Ly8lczol
ZC8iICUgc2VsZi5fc2VydmVyX3NvY2tldC5nZXRzb2NrbmFtZSgpCi0KLSAgICBkZWYgYWNjZXB0
X2FuZF9zZXJ2ZShzZWxmKToKLSAgICAgICAgY29ubiwgY2xpZW50X2FkZHIgPSBzZWxmLl9zZXJ2
ZXJfc29ja2V0LmFjY2VwdCgpCi0gICAgICAgICMgRm9yIFdJTjMyLCB3aGVyZSB0aGUgdGltZW91
dCB2YWx1ZSBmcm9tIHRoZSBsaXN0ZW5pbmcgc29ja2V0Ci0gICAgICAgICMgcHJvcG9nYXRlcyB0
byB0aGUgbmV3bHkgYWNjZXB0ZWQgc29ja2V0LgotICAgICAgICBjb25uLnNldGJsb2NraW5nKFRy
dWUpCi0gICAgICAgIGNvbm4uc2V0c29ja29wdChzb2NrZXQuSVBQUk9UT19UQ1AsIHNvY2tldC5U
Q1BfTk9ERUxBWSwgMSkKLSAgICAgICAgaGFuZGxlciA9IFNtYXJ0U2VydmVyU29ja2V0U3RyZWFt
TWVkaXVtKGNvbm4sIHNlbGYuYmFja2luZ190cmFuc3BvcnQpCi0gICAgICAgIGNvbm5lY3Rpb25f
dGhyZWFkID0gdGhyZWFkaW5nLlRocmVhZChOb25lLCBoYW5kbGVyLnNlcnZlLCBuYW1lPSdzbWFy
dC1zZXJ2ZXItY2hpbGQnKQotICAgICAgICBjb25uZWN0aW9uX3RocmVhZC5zZXREYWVtb24oVHJ1
ZSkKLSAgICAgICAgY29ubmVjdGlvbl90aHJlYWQuc3RhcnQoKQotCi0gICAgZGVmIHN0YXJ0X2Jh
Y2tncm91bmRfdGhyZWFkKHNlbGYpOgotICAgICAgICBzZWxmLl9zZXJ2ZXJfdGhyZWFkID0gdGhy
ZWFkaW5nLlRocmVhZChOb25lLAotICAgICAgICAgICAgICAgIHNlbGYuc2VydmUsCi0gICAgICAg
ICAgICAgICAgbmFtZT0nc2VydmVyLScgKyBzZWxmLmdldF91cmwoKSkKLSAgICAgICAgc2VsZi5f
c2VydmVyX3RocmVhZC5zZXREYWVtb24oVHJ1ZSkKLSAgICAgICAgc2VsZi5fc2VydmVyX3RocmVh
ZC5zdGFydCgpCi0KLSAgICBkZWYgc3RvcF9iYWNrZ3JvdW5kX3RocmVhZChzZWxmKToKLSAgICAg
ICAgc2VsZi5fc2hvdWxkX3Rlcm1pbmF0ZSA9IFRydWUKLSAgICAgICAgIyBBdCBvbmUgcG9pbnQg
d2Ugd291bGQgd2FpdCB0byBqb2luIHRoZSB0aHJlYWRzIGhlcmUsIGJ1dCBpdCBsb29rcwotICAg
ICAgICAjIGxpa2UgdGhleSBkb24ndCBhY3R1YWxseSBleGl0LiAgU28gbm93IHdlIGp1c3QgbGVh
dmUgdGhlbSBydW5uaW5nCi0gICAgICAgICMgYW5kIGV4cGVjdCB0byB0ZXJtaW5hdGUgdGhlIHBy
b2Nlc3MuIC0tIG1icCAyMDA3MDIxNQotICAgICAgICAjIHNlbGYuX3NlcnZlcl9zb2NrZXQuY2xv
c2UoKQotICAgICAgICAjIyBzeXMuc3RkZXJyLndyaXRlKCJ3YWl0aW5nIGZvciBzZXJ2ZXIgdGhy
ZWFkIHRvIGZpbmlzaC4uLiIpCi0gICAgICAgICMjIHNlbGYuX3NlcnZlcl90aHJlYWQuam9pbigp
Ci0KLQotY2xhc3MgU21hcnRUQ1BTZXJ2ZXJfZm9yX3Rlc3RpbmcoU21hcnRUQ1BTZXJ2ZXIpOgot
ICAgICIiIlNlcnZlciBzdWl0YWJsZSBmb3IgdXNlIGJ5IHRyYW5zcG9ydCB0ZXN0cy4KLSAgICAK
LSAgICBUaGlzIHNlcnZlciBpcyBiYWNrZWQgYnkgdGhlIHByb2Nlc3MncyBjd2QuCi0gICAgIiIi
Ci0KLSAgICBkZWYgX19pbml0X18oc2VsZik6Ci0gICAgICAgIHNlbGYuX2hvbWVkaXIgPSB1cmx1
dGlscy5sb2NhbF9wYXRoX3RvX3VybChvcy5nZXRjd2QoKSlbNzpdCi0gICAgICAgICMgVGhlIHNl
cnZlciBpcyBzZXQgdXAgYnkgZGVmYXVsdCBsaWtlIGZvciBzc2ggYWNjZXNzOiB0aGUgY2xpZW50
Ci0gICAgICAgICMgcGFzc2VzIGZpbGVzeXN0ZW0tYWJzb2x1dGUgcGF0aHM7IHRoZXJlZm9yZSB0
aGUgc2VydmVyIG11c3QgbG9vawotICAgICAgICAjIHRoZW0gdXAgcmVsYXRpdmUgdG8gdGhlIHJv
b3QgZGlyZWN0b3J5LiAgaXQgbWlnaHQgYmUgYmV0dGVyIHRvIGFjdAotICAgICAgICAjIGEgcHVi
bGljIHNlcnZlciBhbmQgaGF2ZSB0aGUgc2VydmVyIHJld3JpdGUgcGF0aHMgaW50byB0aGUgdGVz
dAotICAgICAgICAjIGRpcmVjdG9yeS4KLSAgICAgICAgU21hcnRUQ1BTZXJ2ZXIuX19pbml0X18o
c2VsZiwKLSAgICAgICAgICAgIHRyYW5zcG9ydC5nZXRfdHJhbnNwb3J0KHVybHV0aWxzLmxvY2Fs
X3BhdGhfdG9fdXJsKCcvJykpKQotICAgICAgICAKLSAgICBkZWYgZ2V0X2JhY2tpbmdfdHJhbnNw
b3J0KHNlbGYsIGJhY2tpbmdfdHJhbnNwb3J0X3NlcnZlcik6Ci0gICAgICAgICIiIkdldCBhIGJh
Y2tpbmcgdHJhbnNwb3J0IGZyb20gYSBzZXJ2ZXIgd2UgYXJlIGRlY29yYXRpbmcuIiIiCi0gICAg
ICAgIHJldHVybiB0cmFuc3BvcnQuZ2V0X3RyYW5zcG9ydChiYWNraW5nX3RyYW5zcG9ydF9zZXJ2
ZXIuZ2V0X3VybCgpKQotCi0gICAgZGVmIHNldFVwKHNlbGYsIGJhY2tpbmdfdHJhbnNwb3J0X3Nl
cnZlcj1Ob25lKToKLSAgICAgICAgIiIiU2V0IHVwIHNlcnZlciBmb3IgdGVzdGluZyIiIgotICAg
ICAgICBmcm9tIGJ6cmxpYi50cmFuc3BvcnQuY2hyb290IGltcG9ydCBUZXN0aW5nQ2hyb290U2Vy
dmVyCi0gICAgICAgIGlmIGJhY2tpbmdfdHJhbnNwb3J0X3NlcnZlciBpcyBOb25lOgotICAgICAg
ICAgICAgZnJvbSBienJsaWIudHJhbnNwb3J0LmxvY2FsIGltcG9ydCBMb2NhbFVSTFNlcnZlcgot
ICAgICAgICAgICAgYmFja2luZ190cmFuc3BvcnRfc2VydmVyID0gTG9jYWxVUkxTZXJ2ZXIoKQot
ICAgICAgICBzZWxmLmNocm9vdF9zZXJ2ZXIgPSBUZXN0aW5nQ2hyb290U2VydmVyKCkKLSAgICAg
ICAgc2VsZi5jaHJvb3Rfc2VydmVyLnNldFVwKGJhY2tpbmdfdHJhbnNwb3J0X3NlcnZlcikKLSAg
ICAgICAgc2VsZi5iYWNraW5nX3RyYW5zcG9ydCA9IHRyYW5zcG9ydC5nZXRfdHJhbnNwb3J0KAot
ICAgICAgICAgICAgc2VsZi5jaHJvb3Rfc2VydmVyLmdldF91cmwoKSkKLSAgICAgICAgc2VsZi5z
dGFydF9iYWNrZ3JvdW5kX3RocmVhZCgpCi0KLSAgICBkZWYgdGVhckRvd24oc2VsZik6Ci0gICAg
ICAgIHNlbGYuc3RvcF9iYWNrZ3JvdW5kX3RocmVhZCgpCi0KLSAgICBkZWYgZ2V0X2JvZ3VzX3Vy
bChzZWxmKToKLSAgICAgICAgIiIiUmV0dXJuIGEgVVJMIHdoaWNoIHdpbGwgZmFpbCB0byBjb25u
ZWN0IiIiCi0gICAgICAgIHJldHVybiAnYnpyOi8vMTI3LjAuMC4xOjEvJwotCi0KIGNsYXNzIFNt
YXJ0U3RhdChvYmplY3QpOgogCiAgICAgZGVmIF9faW5pdF9fKHNlbGYsIHNpemUsIG1vZGUpOgpA
QCAtMTgzOCw2ICsxNTUwLDcgQEAKIAogZGVmIGdldF90ZXN0X3Blcm11dGF0aW9ucygpOgogICAg
ICIiIlJldHVybiAodHJhbnNwb3J0LCBzZXJ2ZXIpIHBlcm11dGF0aW9ucyBmb3IgdGVzdGluZy4i
IiIKKyAgICBmcm9tIGJ6cmxpYi5zbWFydCBpbXBvcnQgc2VydmVyCiAgICAgIyMjIFdlIG1heSBu
ZWVkIGEgbGl0dGxlIG1vcmUgdGVzdCBmcmFtZXdvcmsgc3VwcG9ydCB0byBjb25zdHJ1Y3QgYW4K
ICAgICAjIyMgYXBwcm9wcmlhdGUgUmVtb3RlVHJhbnNwb3J0IGluIHRoZSBmdXR1cmUuCi0gICAg
cmV0dXJuIFsoU21hcnRUQ1BUcmFuc3BvcnQsIFNtYXJ0VENQU2VydmVyX2Zvcl90ZXN0aW5nKV0K
KyAgICByZXR1cm4gWyhTbWFydFRDUFRyYW5zcG9ydCwgc2VydmVyLlNtYXJ0VENQU2VydmVyX2Zv
cl90ZXN0aW5nKV0KCg==

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200704060
... 11930-wy4emdgu3yu527pm
# revision id: andrew.bennetts at canonical.com-20070406011930-wy4emdgu3yu527pm
# sha1: 09994e30fbdbc4c82b0e6a323572d7b4f02c5a3b
# inventory sha1: f498ea83c4f2e8fc356ae647101ed4dc4be38023
# parent ids:
#   andrew.bennetts at canonical.com-20070405152057-gokz8syll1lk2nrm
# properties:
#   branch-nick: split-smart-part-1-rename

# message:
#   Rename bzrlib/transport/smart.py to bzrlib/transport/remote.py.
#   
#   First part of the code reorganisation from the hpss branch.
# committer: Andrew Bennetts <andrew.bennetts at canonical.com>
# date: Fri 2007-04-06 01:20:57.476999998 +1000

=== renamed file bzrlib/transport/smart.py // bzrlib/transport/remote.py
=== modified file bzrlib/tests/HTTPTestUtil.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy9IVFRQVGVzdFV0aWwucHkKKysrIGJ6cmxpYi90ZXN0cy9IVFRQVGVz
dFV0aWwucHkKQEAgLTI4LDcgKzI4LDcgQEAKICAgICApCiBmcm9tIGJ6cmxpYi50cmFuc3BvcnQg
aW1wb3J0ICgKICAgICBnZXRfdHJhbnNwb3J0LAotICAgIHNtYXJ0LAorICAgIHJlbW90ZSwKICAg
ICApCiAKIApAQCAtMTMwLDcgKzEzMCw3IEBACiAgICAgICAgICMgd2UgaGF2ZSB0byBzdG9wIGVh
cmx5IGR1ZSB0byBlcnJvciwgYnV0IHdlIHdvdWxkIGFsc28gaGF2ZSB0byB1c2UgdGhlCiAgICAg
ICAgICMgSFRUUCB0cmFpbGVyIGZhY2lsaXR5IHdoaWNoIG1heSBub3QgYmUgd2lkZWx5IGF2YWls
YWJsZS4KICAgICAgICAgb3V0X2J1ZmZlciA9IFN0cmluZ0lPKCkKLSAgICAgICAgc21hcnRfcHJv
dG9jb2xfcmVxdWVzdCA9IHNtYXJ0LlNtYXJ0U2VydmVyUmVxdWVzdFByb3RvY29sT25lKAorICAg
ICAgICBzbWFydF9wcm90b2NvbF9yZXF1ZXN0ID0gcmVtb3RlLlNtYXJ0U2VydmVyUmVxdWVzdFBy
b3RvY29sT25lKAogICAgICAgICAgICAgICAgIHRyYW5zcG9ydCwgb3V0X2J1ZmZlci53cml0ZSkK
ICAgICAgICAgIyBpZiB0aGlzIGZhaWxzLCB3ZSBzaG91bGQgcmV0dXJuIDQwMCBiYWQgcmVxdWVz
dCwgYnV0IGZhaWx1cmUgaXMKICAgICAgICAgIyBmYWlsdXJlIGZvciBub3cgLSBSQkMgMjAwNjA5
MTkKCg==

=== modified file bzrlib/tests/blackbox/test_serve.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy9ibGFja2JveC90ZXN0X3NlcnZlLnB5CisrKyBienJsaWIvdGVzdHMv
YmxhY2tib3gvdGVzdF9zZXJ2ZS5weQpAQCAtMzEsNyArMzEsNyBAQAogZnJvbSBienJsaWIuYnpy
ZGlyIGltcG9ydCBCenJEaXIKIGZyb20gYnpybGliLmVycm9ycyBpbXBvcnQgUGFyYW1pa29Ob3RQ
cmVzZW50CiBmcm9tIGJ6cmxpYi50ZXN0cyBpbXBvcnQgVGVzdENhc2VXaXRoVHJhbnNwb3J0LCBU
ZXN0U2tpcHBlZAotZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCBnZXRfdHJhbnNwb3J0LCBz
bWFydAorZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCBnZXRfdHJhbnNwb3J0LCByZW1vdGUK
IAogCiBjbGFzcyBUZXN0QnpyU2VydmUoVGVzdENhc2VXaXRoVHJhbnNwb3J0KToKQEAgLTY4LDkg
KzY4LDkgQEAKICAgICAgICAgIyBDb25uZWN0IHRvIHRoZSBzZXJ2ZXIKICAgICAgICAgIyBXZSB1
c2UgdGhpcyB1cmwgYmVjYXVzZSB3aGlsZSB0aGlzIGlzIG5vIHZhbGlkIFVSTCB0byBjb25uZWN0
IHRvIHRoaXMKICAgICAgICAgIyBzZXJ2ZXIgaW5zdGFuY2UsIHRoZSB0cmFuc3BvcnQgbmVlZHMg
YSBVUkwuCi0gICAgICAgIG1lZGl1bSA9IHNtYXJ0LlNtYXJ0U2ltcGxlUGlwZXNDbGllbnRNZWRp
dW0oCisgICAgICAgIG1lZGl1bSA9IHJlbW90ZS5TbWFydFNpbXBsZVBpcGVzQ2xpZW50TWVkaXVt
KAogICAgICAgICAgICAgcHJvY2Vzcy5zdGRvdXQsIHByb2Nlc3Muc3RkaW4pCi0gICAgICAgIHRy
YW5zcG9ydCA9IHNtYXJ0LlNtYXJ0VHJhbnNwb3J0KCdienI6Ly9sb2NhbGhvc3QvJywgbWVkaXVt
PW1lZGl1bSkKKyAgICAgICAgdHJhbnNwb3J0ID0gcmVtb3RlLlNtYXJ0VHJhbnNwb3J0KCdienI6
Ly9sb2NhbGhvc3QvJywgbWVkaXVtPW1lZGl1bSkKICAgICAgICAgcmV0dXJuIHByb2Nlc3MsIHRy
YW5zcG9ydAogCiAgICAgZGVmIHN0YXJ0X3NlcnZlcl9wb3J0KHNlbGYsIGV4dHJhX29wdGlvbnM9
KCkpOgoK

=== modified file bzrlib/tests/test_smart_transport.py // encoding:base64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3NtYXJ0X3RyYW5zcG9ydC5weQorKysgYnpybGliL3Rlc3Rz
L3Rlc3Rfc21hcnRfdHJhbnNwb3J0LnB5CkBAIC0zOCwxMCArMzgsMTEgQEAKICAgICAgICAgZ2V0
X3RyYW5zcG9ydCwKICAgICAgICAgbG9jYWwsCiAgICAgICAgIG1lbW9yeSwKLSAgICAgICAgc21h
cnQsCisgICAgICAgIHJlbW90ZSwKICAgICAgICAgKQogZnJvbSBienJsaWIudHJhbnNwb3J0Lmh0
dHAgaW1wb3J0IFNtYXJ0Q2xpZW50SFRUUE1lZGl1bVJlcXVlc3QKIAorc21hcnQgPSByZW1vdGUK
IAogY2xhc3MgU3RyaW5nSU9TU0hWZW5kb3Iob2JqZWN0KToKICAgICAiIiJBIFNTSCB2ZW5kb3Ig
dGhhdCB1c2VzIFN0cmluZ0lPIHRvIGJ1ZmZlciB3cml0ZXMgYW5kIGFuc3dlciByZWFkcy4iIiIK
Cg==

=== modified file bzrlib/tests/test_transport_implementations.py // encoding:ba
... se64
LS0tIGJ6cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydF9pbXBsZW1lbnRhdGlvbnMucHkKKysrIGJ6
cmxpYi90ZXN0cy90ZXN0X3RyYW5zcG9ydF9pbXBsZW1lbnRhdGlvbnMucHkKQEAgLTM4LDcgKzM4
LDcgQEAKIGZyb20gYnpybGliLnN5bWJvbF92ZXJzaW9uaW5nIGltcG9ydCB6ZXJvX2VsZXZlbgog
ZnJvbSBienJsaWIudGVzdHMgaW1wb3J0IFRlc3RDYXNlSW5UZW1wRGlyLCBUZXN0U2tpcHBlZAog
ZnJvbSBienJsaWIudGVzdHMudGVzdF90cmFuc3BvcnQgaW1wb3J0IFRlc3RUcmFuc3BvcnRJbXBs
ZW1lbnRhdGlvbgotZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCBtZW1vcnksIHNtYXJ0Citm
cm9tIGJ6cmxpYi50cmFuc3BvcnQgaW1wb3J0IG1lbW9yeSwgcmVtb3RlCiBpbXBvcnQgYnpybGli
LnRyYW5zcG9ydAogCiAKQEAgLTEzMDYsNyArMTMwNiw3IEBACiAgICAgICAgIHRyYW5zcG9ydCA9
IHNlbGYuZ2V0X3RyYW5zcG9ydCgpCiAgICAgICAgIHRyeToKICAgICAgICAgICAgIGNsaWVudF9t
ZWRpdW0gPSB0cmFuc3BvcnQuZ2V0X3NtYXJ0X21lZGl1bSgpCi0gICAgICAgICAgICBzZWxmLmFz
c2VydElzSW5zdGFuY2UoY2xpZW50X21lZGl1bSwgc21hcnQuU21hcnRDbGllbnRNZWRpdW0pCisg
ICAgICAgICAgICBzZWxmLmFzc2VydElzSW5zdGFuY2UoY2xpZW50X21lZGl1bSwgcmVtb3RlLlNt
YXJ0Q2xpZW50TWVkaXVtKQogICAgICAgICBleGNlcHQgZXJyb3JzLk5vU21hcnRNZWRpdW06CiAg
ICAgICAgICAgICAjIGFzIGxvbmcgYXMgd2UgZ290IGl0IHdlJ3JlIGZpbmUKICAgICAgICAgICAg
IHBhc3MKCg==

=== modified file bzrlib/transport/__init__.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvX19pbml0X18ucHkKKysrIGJ6cmxpYi90cmFuc3BvcnQvX19p
bml0X18ucHkKQEAgLTEyNTEsMTEgKzEyNTEsMTEgQEAKICAgICAgICAgICAgICAgICAgICAgICAg
ICdienJsaWIudHJhbnNwb3J0LmZha2V2ZmF0JywKICAgICAgICAgICAgICAgICAgICAgICAgICdG
YWtlVkZBVFRyYW5zcG9ydERlY29yYXRvcicpCiByZWdpc3Rlcl9sYXp5X3RyYW5zcG9ydCgnYnpy
Oi8vJywKLSAgICAgICAgICAgICAgICAgICAgICAgICdienJsaWIudHJhbnNwb3J0LnNtYXJ0JywK
KyAgICAgICAgICAgICAgICAgICAgICAgICdienJsaWIudHJhbnNwb3J0LnJlbW90ZScsCiAgICAg
ICAgICAgICAgICAgICAgICAgICAnU21hcnRUQ1BUcmFuc3BvcnQnKQogcmVnaXN0ZXJfbGF6eV90
cmFuc3BvcnQoJ2J6citodHRwOi8vJywKLSAgICAgICAgICAgICAgICAgICAgICAgICdienJsaWIu
dHJhbnNwb3J0LnNtYXJ0JywKKyAgICAgICAgICAgICAgICAgICAgICAgICdienJsaWIudHJhbnNw
b3J0LnJlbW90ZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAnU21hcnRIVFRQVHJhbnNwb3J0
JykKIHJlZ2lzdGVyX2xhenlfdHJhbnNwb3J0KCdienIrc3NoOi8vJywKLSAgICAgICAgICAgICAg
ICAgICAgICAgICdienJsaWIudHJhbnNwb3J0LnNtYXJ0JywKKyAgICAgICAgICAgICAgICAgICAg
ICAgICdienJsaWIudHJhbnNwb3J0LnJlbW90ZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAn
U21hcnRTU0hUcmFuc3BvcnQnKQoK

=== modified file bzrlib/transport/http/__init__.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvaHR0cC9fX2luaXRfXy5weQorKysgYnpybGliL3RyYW5zcG9y
dC9odHRwL19faW5pdF9fLnB5CkBAIC0yOSw3ICsyOSw3IEBACiBmcm9tIGJ6cmxpYiBpbXBvcnQg
ZXJyb3JzLCB1aQogZnJvbSBienJsaWIudHJhY2UgaW1wb3J0IG11dHRlcgogZnJvbSBienJsaWIu
dHJhbnNwb3J0IGltcG9ydCAoCi0gICAgc21hcnQsCisgICAgcmVtb3RlLAogICAgIFRyYW5zcG9y
dCwKICAgICApCiAKQEAgLTExMyw3ICsxMTMsNyBAQAogICAgIHJldHVybiBtCiAKIAotY2xhc3Mg
SHR0cFRyYW5zcG9ydEJhc2UoVHJhbnNwb3J0LCBzbWFydC5TbWFydENsaWVudE1lZGl1bSk6Citj
bGFzcyBIdHRwVHJhbnNwb3J0QmFzZShUcmFuc3BvcnQsIHJlbW90ZS5TbWFydENsaWVudE1lZGl1
bSk6CiAgICAgIiIiQmFzZSBjbGFzcyBmb3IgaHR0cCBpbXBsZW1lbnRhdGlvbnMuCiAKICAgICBE
b2VzIFVSTCBwYXJzaW5nLCBldGMsIGJ1dCBub3QgYW55IG5ldHdvcmsgSU8uCkBAIC01MDUsMTEg
KzUwNSwxMSBAQAogICAgICAgICByZXR1cm4gYm9keV9maWxlbGlrZQogCiAKLWNsYXNzIFNtYXJ0
Q2xpZW50SFRUUE1lZGl1bVJlcXVlc3Qoc21hcnQuU21hcnRDbGllbnRNZWRpdW1SZXF1ZXN0KToK
K2NsYXNzIFNtYXJ0Q2xpZW50SFRUUE1lZGl1bVJlcXVlc3QocmVtb3RlLlNtYXJ0Q2xpZW50TWVk
aXVtUmVxdWVzdCk6CiAgICAgIiIiQSBTbWFydENsaWVudE1lZGl1bVJlcXVlc3QgdGhhdCB3b3Jr
cyB3aXRoIGFuIEhUVFAgbWVkaXVtLiIiIgogCiAgICAgZGVmIF9faW5pdF9fKHNlbGYsIG1lZGl1
bSk6Ci0gICAgICAgIHNtYXJ0LlNtYXJ0Q2xpZW50TWVkaXVtUmVxdWVzdC5fX2luaXRfXyhzZWxm
LCBtZWRpdW0pCisgICAgICAgIHJlbW90ZS5TbWFydENsaWVudE1lZGl1bVJlcXVlc3QuX19pbml0
X18oc2VsZiwgbWVkaXVtKQogICAgICAgICBzZWxmLl9idWZmZXIgPSAnJwogCiAgICAgZGVmIF9h
Y2NlcHRfYnl0ZXMoc2VsZiwgYnl0ZXMpOgoK

=== modified file bzrlib/transport/http/wsgi.py // encoding:base64
LS0tIGJ6cmxpYi90cmFuc3BvcnQvaHR0cC93c2dpLnB5CisrKyBienJsaWIvdHJhbnNwb3J0L2h0
dHAvd3NnaS5weQpAQCAtMjIsNyArMjIsNyBAQAogCiBmcm9tIGNTdHJpbmdJTyBpbXBvcnQgU3Ry
aW5nSU8KIAotZnJvbSBienJsaWIudHJhbnNwb3J0IGltcG9ydCBjaHJvb3QsIGdldF90cmFuc3Bv
cnQsIHNtYXJ0Citmcm9tIGJ6cmxpYi50cmFuc3BvcnQgaW1wb3J0IGNocm9vdCwgZ2V0X3RyYW5z
cG9ydCwgcmVtb3RlCiBmcm9tIGJ6cmxpYi51cmx1dGlscyBpbXBvcnQgbG9jYWxfcGF0aF90b191
cmwKICAgICAKIAoK

=== modified directory  // last-changed:andrew.bennetts at canonical.com-200704051
... 52057-gokz8syll1lk2nrm
# revision id: andrew.bennetts at canonical.com-20070405152057-gokz8syll1lk2nrm
# sha1: 832f89a360e4e4b44df243a8a06206f28171b756
# inventory sha1: be27509e511e0c49a3eef322d5983af56dccf222
# parent ids:
#   pqm at pqm.ubuntu.com-20070404213903-fe78a7a55c37ee95
# properties:
#   branch-nick: split-smart-part-1-rename



More information about the bazaar mailing list