[PATCH] wireproto: use base64 instead of hex for known/getbundle

Steven Brown stevengbrown at gmail.com
Sun May 1 11:51:11 CDT 2011


On 1 May 2011 18:35, Peter Arrenbrecht <peter.arrenbrecht at gmail.com> wrote:
> # HG changeset patch
> # User Peter Arrenbrecht <peter.arrenbrecht at gmail.com>
> # Date 1304246106 -7200
> wireproto: use base64 instead of hex for known/getbundle
>
> Saves a couple of bytes per node id being sent across the
> wire. Introduces node.to/fromb64 and wireproto.en/decodelistb64.
>
> diff --git a/mercurial/node.py b/mercurial/node.py
> --- a/mercurial/node.py
> +++ b/mercurial/node.py
> @@ -5,7 +5,7 @@
>  # This software may be used and distributed according to the terms of the
>  # GNU General Public License version 2 or any later version.
>
> -import binascii
> +import binascii, base64
>
>  nullrev = -1
>  nullid = "\0" * 20
> @@ -14,5 +14,8 @@
>  hex = binascii.hexlify
>  bin = binascii.unhexlify
>
> +tob64 = base64.encodestring
> +fromb64 = base64.decodestring
> +
>  def short(node):
>     return hex(node[:6])
> diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
> --- a/mercurial/wireproto.py
> +++ b/mercurial/wireproto.py
> @@ -7,7 +7,7 @@
>
>  import urllib, tempfile, os, sys
>  from i18n import _
> -from node import bin, hex
> +from node import bin, hex, tob64, fromb64
>  import changegroup as changegroupmod
>  import repo, error, encoding, util, store
>  import pushkey as pushkeymod
> @@ -22,6 +22,14 @@
>  def encodelist(l, sep=' '):
>     return sep.join(map(hex, l))
>
> +def decodelistb64(l, sep=' '):
> +    if l:
> +        return map(fromb64, l.split(sep))
> +    return []
> +
> +def encodelistb64(l, sep=' '):
> +    return sep.join(map(tob64, l))
> +
>  # client side
>
>  class wirerepository(repo.repository):
> @@ -41,7 +49,7 @@
>             self._abort(error.ResponseError(_("unexpected response:"), d))
>
>     def known(self, nodes):
> -        n = encodelist(nodes)
> +        n = encodelistb64(nodes)
>         d = self._call("known", nodes=n)
>         try:
>             return [bool(int(f)) for f in d]
> @@ -127,9 +135,9 @@
>         self.requirecap('getbundle', _('look up remote changes'))
>         opts = {}
>         if heads is not None:
> -            opts['heads'] = encodelist(heads)
> +            opts['heads'] = encodelistb64(heads)
>         if common is not None:
> -            opts['common'] = encodelist(common)
> +            opts['common'] = encodelistb64(common)
>         f = self._callstream("getbundle", **opts)
>         return changegroupmod.unbundle10(self._decompress(f), 'UN')
>
> @@ -254,7 +262,7 @@
>  def getbundle(repo, proto, others):
>     opts = options('getbundle', ['heads', 'common'], others)
>     for k, v in opts.iteritems():
> -        opts[k] = decodelist(v)
> +        opts[k] = decodelistb64(v)
>     cg = repo.getbundle('serve', **opts)
>     return streamres(proto.groupchunks(cg))
>
> @@ -288,7 +296,7 @@
>     return "%s %s\n" % (success, r)
>
>  def known(repo, proto, nodes):
> -    return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes)))
> +    return ''.join(b and "1" or "0" for b in repo.known(decodelistb64(nodes)))
>
>  def pushkey(repo, proto, namespace, key, old, new):
>     # compatibility with pre-1.8 clients which were accidentally
> diff --git a/tests/test-getbundle.t b/tests/test-getbundle.t
> --- a/tests/test-getbundle.t
> +++ b/tests/test-getbundle.t
> @@ -247,7 +247,7 @@
>   * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
>   * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - (glob)
>   * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
> -  * - - [*] "GET /?cmd=getbundle&common=c1818a9f5977dd4139a48f93f5425c67d44a9368+ea919464b16e003894c48b6cb68df3cd9411b544&heads=6b57ee934bb2996050540f84cdfc8dcad1e7267d+2114148793524fd045998f71a45b0aaf139f752b HTTP/1.1" 200 - (glob)
> +  * - - [*] "GET /?cmd=getbundle&common=wYGKn1l33UE5pI%2BT9UJcZ9RKk2g%3D%0A+6pGUZLFuADiUxItsto3zzZQRtUQ%3D%0A&heads=a1fuk0uymWBQVA%2BEzfyNytHnJn0%3D%0A+IRQUh5NST9BFmY9xpFsKrxOfdSs%3D%0A HTTP/1.1" 200 - (glob)
>
>   $ cat error.log
>
> diff --git a/tests/test-http-proxy.t b/tests/test-http-proxy.t
> --- a/tests/test-http-proxy.t
> +++ b/tests/test-http-proxy.t
> @@ -103,18 +103,18 @@
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys&namespace=bookmarks HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob)
> -  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - - (glob)
> +  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=AAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%0A&heads=gxgOeEXeQgobtGiW%2FV%2FgUpT41ik%3D%0A HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys&namespace=bookmarks HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob)
> -  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - - (glob)
> +  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=AAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%0A&heads=gxgOeEXeQgobtGiW%2FV%2FgUpT41ik%3D%0A HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys&namespace=bookmarks HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob)
> -  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - - (glob)
> +  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=AAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%0A&heads=gxgOeEXeQgobtGiW%2FV%2FgUpT41ik%3D%0A HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys&namespace=bookmarks HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=heads HTTP/1.1" - - (glob)
> -  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - - (glob)
> +  * - - [*] "GET http://localhost:$HGPORT/?cmd=getbundle&common=AAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%0A&heads=gxgOeEXeQgobtGiW%2FV%2FgUpT41ik%3D%0A HTTP/1.1" - - (glob)
>   * - - [*] "GET http://localhost:$HGPORT/?cmd=listkeys&namespace=bookmarks HTTP/1.1" - - (glob)
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>

The base64.encodestring function adds '\n' to the end of every encoded
string, and is part of the "legacy interface" according to the Python
docs.

Have you considered using base64.b64encode instead?


More information about the Mercurial-devel mailing list